As noted in the Container Lifecycle documentation, Containers on Aptible are fundamentally ephemeral, and you should never use the filesystem for long-term file or data storage.The best approach for storing files uploaded by your customers (or, more broadly speaking, any blob data generated by your app, such as PDFs, etc.) is to use a third-party object store, such as AWS S3.You can store data in an Aptible database, but often at a performance cost.
If you are storing regulated or sensitive information, ensure you have the proper agreements with your storage provider. For example, you’ll need to execute a BAA with AWS and use encryption (client-side or server-side) to store PHI in AWS S3.
For storing PHI on Amazon S3, you must get a separate BAA with Amazon Web Services. This BAA will require that you encrypt all data stored on S3. You have three options for implementing encryption, ranked from best to worst based on the combination of ease of implementation and security:
Server-side encryption with customer-provided keys (SSE-C): You specify the key when uploading and downloading objects to/from S3. You are responsible for remembering the encryption key but don’t have to choose or maintain an encryption library.
Client-side encryption (CSE): This approach is the most challenging but also gives you complete control. You pick an encryption library and implement the encryption/decryption logic.
Server-side encryption with Amazon-provided keys (SSE): This is the most straightforward approach but the least secure. You need only specify that encryption should occur on PUT, and you never need to keep track of encryption keys. The downside is that if any of your privileged AWS accounts (or access keys) are compromised, your S3 data may be compromised and unprotected by a secondary key.
There are two ways to serve S3 media files:
Generate a pre-signed URL so that the client can access them directly from S3 (note: this will not work if you’re using client-side encryption)
Route all media requests through your app, fetch the S3 file within your app code, then re-serve it to the client.
The first approach is superior from a performance perspective. However, if these are PHI-sensitive media files, we recommend the second approach due to the control it gives you concerning audit logging, as you can more easily connect specific S3 file access to individual users in your system.
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Aptible","colors":{"primary":"#4361FF","light":"#4361FF","dark":"#4361FF"},"logo":{"light":"https://mintcdn.com/aptible/nK6qZs9Dv-SJIud9/logo/light-opti9.png?fit=max\u0026auto=format\u0026n=nK6qZs9Dv-SJIud9\u0026q=85\u0026s=116d34dbfb42c6d5af0b854f5a929001","dark":"https://mintcdn.com/aptible/nK6qZs9Dv-SJIud9/logo/dark-opti9.png?fit=max\u0026auto=format\u0026n=nK6qZs9Dv-SJIud9\u0026q=85\u0026s=a1e42f8cf8df1654a38c67a42a6fd308","href":"https://www.aptible.com/"},"favicon":"https://mintcdn.com/aptible/znQKnZ_9oCdAaQ49/favicon.svg?fit=max\u0026auto=format\u0026n=znQKnZ_9oCdAaQ49\u0026q=85\u0026s=f462b06cd86ceae1537728240a8d53e8","background":{"decoration":"grid"},"navbar":{"links":[{"href":"https://app.aptible.com/support","label":"Support"}],"primary":{"type":"button","label":"Sign up","href":"https://app.aptible.com/signup"}},"footer":{"socials":{"twitter":"https://twitter.com/aptible?lang=en","linkedin":"https://www.linkedin.com/company/aptible","github":"https://github.com/aptible"},"links":[{"header":"Resources","items":[{"label":"Blog","href":"https://www.aptible.com/blog"},{"label":"Changelog","href":"https://www.aptible.com/changelog"},{"label":"Trust Center","href":"https://trust.aptible.com/"}]},{"header":"Support","items":[{"label":"Contact Us","href":"https://app.aptible.com/support"},{"label":"Status Page","href":"https://status.aptible.com/"}]}]},"search":{"prompt":"Search or ask AI..."},"seo":{"metatags":{"canonical":"https://www.aptible.com/docs"}},"integrations":{"ga4":{"measurementId":"G-W2CQG3K9LP"}},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Contact Support","icon":"headset","href":"https://app.aptible.com/support"},{"anchor":"Changelog","icon":"sparkles","href":"https://www.aptible.com/changelog"},{"anchor":"Trust Center","icon":"lock","href":"https://trust.aptible.com/"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"aptible","hasAudioNarration":false,"actualSubdomain":"aptible","customDomains":["www.aptible.com"],"gitSource":{"type":"github","owner":"aptible","repo":"mintlify-docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae3f0e529c8303331bca64b","collectionId":"3a70b479-f77b-4b35-a029-03001ed8a712","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae3f0e529c8303331bca64b"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"ENABLED"},"CONTEXTUAL_FEEDBACK":{"status":"ENABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae3f0e529c8303331bca64b","clientVersion":"0.0.4043","searchFilterCounts":[{"language":"default","tag":"Documentation","count":245},{"language":"default","tag":"Platform","count":122},{"language":"default","tag":"Guides","count":117},{"language":"default","tag":"Reference","count":96},{"language":"default","tag":"Aptible CLI","count":92},{"language":"default","tag":"How to Guides","count":89},{"language":"default","tag":"All CLI Commands","count":89},{"language":"default","tag":"Apps","count":37},{"language":"default","tag":"App Guides","count":35},{"language":"default","tag":"Support \u0026 Troubleshooting","count":28}]},"assistantConfig":{},"basePath":"/docs","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"how-to-guides/app-guides/use-s3-to-accept-file-uploads","slug":"/how-to-guides/app-guides/use-s3-to-accept-file-uploads","pageMetadata":{"title":"How to use S3 to accept file uploads","description":"Learn how to connect your app to S3 to accept file uploads","href":"/how-to-guides/app-guides/use-s3-to-accept-file-uploads"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Learn how to connect your app to S3 to accept file uploads\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,li:`li`,ol:`ol`,p:`p`,strong:`strong`,..._provideComponents(),...props.components},{Heading,Warning}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`overview`,children:`Overview`}),`\n`,_jsxs(_components.p,{children:[`As noted in the `,_jsx(_components.a,{href:`/core-concepts/architecture/containers/overview`,children:`Container Lifecycle`}),` documentation, `,_jsx(_components.a,{href:`/core-concepts/architecture/containers/overview`,children:`Containers`}),` on Aptible are fundamentally ephemeral, and you should `,_jsx(_components.strong,{children:`never use the filesystem for long-term file or data storage`}),`.`]}),`\n`,_jsx(_components.p,{children:`The best approach for storing files uploaded by your customers (or, more broadly speaking, any blob data generated by your app, such as PDFs, etc.) is to use a third-party object store, such as AWS S3.`}),`\n`,_jsxs(_components.p,{children:[`You can store data in an Aptible `,_jsx(_components.a,{href:`/core-concepts/managed-databases/managing-databases/overview`,children:`database`}),`, but often at a performance cost.`]}),`\n`,_jsx(Heading,{level:`2`,id:`using-aws-s3-for-phi`,children:`Using AWS S3 for PHI`}),`\n`,_jsx(Warning,{children:`If you are storing regulated or sensitive information, ensure you have the proper agreements with your storage provider. For example, you’ll need to execute a BAA with AWS and use encryption (client-side or server-side) to store PHI in AWS S3.`}),`\n`,_jsx(_components.p,{children:`For storing PHI on Amazon S3, you must get a separate BAA with Amazon Web Services. This BAA will require that you encrypt all data stored on S3. You have three options for implementing encryption, ranked from best to worst based on the combination of ease of implementation and security:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Server-side encryption with customer-provided keys`}),` (`,_jsx(_components.a,{href:`https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html`,children:`SSE-C`}),`): You specify the key when uploading and downloading objects to/from S3. You are responsible for remembering the encryption key but don’t have to choose or maintain an encryption library.`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Client-side encryption`}),` (`,_jsx(_components.a,{href:`https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html`,children:`CSE`}),`): This approach is the most challenging but also gives you complete control. You pick an encryption library and implement the encryption/decryption logic.`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Server-side encryption with Amazon-provided keys`}),` (`,_jsx(_components.a,{href:`https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html`,children:`SSE`}),`): This is the most straightforward approach but the least secure. You need only specify that encryption should occur on PUT, and you never need to keep track of encryption keys. The downside is that if any of your privileged AWS accounts (or access keys) are compromised, your S3 data may be compromised and unprotected by a secondary key.`]}),`\n`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`There are two ways to serve S3 media files:`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`\n`,_jsx(_components.p,{children:`Generate a pre-signed URL so that the client can access them directly from S3 (note: this will not work if you’re using client-side encryption)`}),`\n`]}),`\n`,_jsxs(_components.li,{children:[`\n`,_jsx(_components.p,{children:`Route all media requests through your app, fetch the S3 file within your app code, then re-serve it to the client.`}),`\n`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`The first approach is superior from a performance perspective. However, if these are PHI-sensitive media files, we recommend the second approach due to the control it gives you concerning audit logging, as you can more easily connect specific S3 file access to individual users in your system.`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"How to use S3 to accept file uploads","description":"Learn how to connect your app to S3 to accept file uploads","href":"/how-to-guides/app-guides/use-s3-to-accept-file-uploads"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Overview","slug":"overview","depth":2,"children":[]},{"title":"Using AWS S3 for PHI","slug":"using-aws-s3-for-phi","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"aptible","siteName":"Aptible","title":"How to use S3 to accept file uploads - Aptible","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-07T19:58:56.280Z","originalFileLocation":"how-to-guides/app-guides/use-s3-to-accept-file-uploads.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Learn how to connect your app to S3 to accept file uploads\">\u003cmeta data-mint-head name=\"application-name\" content=\"Aptible\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"How to use S3 to accept file uploads - Aptible\">\u003cmeta data-mint-head property=\"og:description\" content=\"Learn how to connect your app to S3 to accept file uploads\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Aptible\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://aptible.mintlify.app/_mintlify/api/og/v2?division=App+Guides\u0026amp;title=How+to+use+S3+to+accept+file+uploads\u0026amp;description=Learn+how+to+connect+your+app+to+S3+to+accept+file+uploads\u0026amp;theme=c333d236eff7eda320fab2dd\u0026amp;signature=8df4d8ac1d71a8685568c412a4803313d29119d03aa4b96c06d0c8fb4c6c3f2f\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"How to use S3 to accept file uploads - Aptible\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Learn how to connect your app to S3 to accept file uploads\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://aptible.mintlify.app/_mintlify/api/og/v2?division=App+Guides\u0026amp;title=How+to+use+S3+to+accept+file+uploads\u0026amp;description=Learn+how+to+connect+your+app+to+S3+to+accept+file+uploads\u0026amp;theme=c333d236eff7eda320fab2dd\u0026amp;signature=8df4d8ac1d71a8685568c412a4803313d29119d03aa4b96c06d0c8fb4c6c3f2f\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/aptible/Sr55mlb_VATXGmMy/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Aptible\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#4361FF\">\u003clink data-mint-head rel=\"canonical\" href=\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://www.aptible.com/#organization\",\"name\":\"Aptible\",\"url\":\"https://www.aptible.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/aptible/nK6qZs9Dv-SJIud9/logo/light-opti9.png?fit=max\u0026auto=format\u0026n=nK6qZs9Dv-SJIud9\u0026q=85\u0026s=116d34dbfb42c6d5af0b854f5a929001\"}},{\"@type\":\"WebSite\",\"@id\":\"https://www.aptible.com/docs#website\",\"name\":\"Aptible\",\"url\":\"https://www.aptible.com/docs\",\"publisher\":{\"@id\":\"https://www.aptible.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads#webpage\",\"url\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads\",\"name\":\"How to use S3 to accept file uploads\",\"description\":\"Learn how to connect your app to S3 to accept file uploads\",\"dateModified\":\"2026-10-07T19:58:56.280Z\",\"isPartOf\":{\"@id\":\"https://www.aptible.com/docs#website\"},\"breadcrumb\":{\"@id\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"How to Guides\",\"item\":\"https://www.aptible.com/docs/how-to-guides/guides-overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"App Guides\",\"item\":\"https://www.aptible.com/docs/how-to-guides/app-guides/overview\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How to use S3 to accept file uploads\",\"item\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads#article\",\"headline\":\"How to use S3 to accept file uploads\",\"name\":\"How to use S3 to accept file uploads\",\"description\":\"Learn how to connect your app to S3 to accept file uploads\",\"url\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads\",\"mainEntityOfPage\":{\"@id\":\"https://www.aptible.com/docs/how-to-guides/app-guides/use-s3-to-accept-file-uploads#webpage\"},\"dateModified\":\"2026-10-07T19:58:56.280Z\",\"publisher\":{\"@id\":\"https://www.aptible.com/#organization\"},\"isPartOf\":{\"@id\":\"https://www.aptible.com/docs#website\"}}]}\u003c/script>","siteName":"Aptible","nav":{"global":{"anchors":[{"anchor":"Contact Support","icon":"headset","href":"https://app.aptible.com/support"},{"anchor":"Changelog","icon":"sparkles","href":"https://www.aptible.com/changelog"},{"anchor":"Trust Center","icon":"lock","href":"https://trust.aptible.com/"}]},"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":"/getting-started/home"}]},{"tab":"Guides","groups":[{"group":"How to Guides","pages":[{"title":"Browse Guides","href":"/how-to-guides/guides-overview"},{"group":"App Guides","pages":[{"title":"All App Guides","href":"/how-to-guides/app-guides/overview"},{"title":"How to create an app","href":"/how-to-guides/app-guides/how-to-create-app"},{"title":"How to scale apps and services","href":"/how-to-guides/app-guides/how-to-scale-apps-services"},{"title":"How to set and modify configuration variables","href":"/how-to-guides/app-guides/set-modify-config-variables"},{"title":"How to deploy a preview app to Aptible using Github Actions","href":"/how-to-guides/app-guides/deploy-preview-app"},{"title":"How to deploy to Aptible with CI/CD","href":"/how-to-guides/app-guides/how-to-deploy-aptible-ci-cd"},{"title":"How to use AWS Secrets Manager with Aptible Apps","href":"/how-to-guides/app-guides/how-to-use-aws-secrets-manager"},{"title":"How to define services","href":"/how-to-guides/app-guides/define-services"},{"title":"How to deploy via Docker Image","href":"/how-to-guides/app-guides/deploy-docker-image"},{"title":"How to deploy from Git","href":"/how-to-guides/app-guides/deploy-from-git"},{"title":"How to migrate from deploying via Docker Image to deploying via Git","href":"/how-to-guides/app-guides/deploying-docker-image-to-git"},{"title":"Horizontal Autoscaling Guide","href":"/how-to-guides/app-guides/horizontal-autoscaling-guide"},{"group":"Integrate Aptible with CI","pages":[{"title":"How to integrate Aptible with CI Platforms","sidebarTitle":"Overview","href":"/how-to-guides/app-guides/integrate-aptible-with-ci/overview"},{"title":"Circle CI","href":"/how-to-guides/app-guides/integrate-aptible-with-ci/circle-cl"},{"title":"Codeship","href":"/how-to-guides/app-guides/integrate-aptible-with-ci/codeship"},{"title":"Jenkins","href":"/how-to-guides/app-guides/integrate-aptible-with-ci/jenkins"},{"title":"Travis CI","href":"/how-to-guides/app-guides/integrate-aptible-with-ci/travis-cl"}]},{"title":"How to synchronize configuration and code changes","href":"/how-to-guides/app-guides/synchronize-config-code-changes"},{"title":"How to migrate from deploying via Git to deploying via Docker image","href":"/how-to-guides/app-guides/migrate-dockerfile-to-direct-image-deploy"},{"title":"Deploy Metric Drain with Terraform","href":"/how-to-guides/app-guides/deploy-metric-drain-with-terraform"},{"title":"Getting Started with Docker","href":"/how-to-guides/app-guides/getting-started-with-docker"},{"title":"How to access configuration variables during Docker build","href":"/how-to-guides/app-guides/access-config-vars-during-docker-build"},{"title":"How to generate certificate signing requests","href":"/how-to-guides/app-guides/generate-certificate-signing-requests"},{"title":"How to expose a web app to the Internet","href":"/how-to-guides/app-guides/expose-web-app-to-internet"},{"title":"Set Up Cloudflare with Aptible Endpoints","href":"/how-to-guides/app-guides/set-up-cloudflare-with-aptible-endpoints"},{"title":"Configuring Nginx proxies on Aptible","href":"/how-to-guides/app-guides/use-nginx-with-aptible-endpoints"},{"title":"How to make Git deploys faster","href":"/how-to-guides/app-guides/make-docker-deploys-faster"},{"group":"Use Domain Apex With Endpoints","pages":[{"title":"How to use Domain Apex with Endpoints","sidebarTitle":"Overview","href":"/how-to-guides/app-guides/use-domain-apex-with-endpoints/overview"},{"title":"Domain Apex ALIAS","href":"/how-to-guides/app-guides/use-domain-apex-with-endpoints/domain-apex-alias"},{"title":"AWS Domain Apex Redirect","href":"/how-to-guides/app-guides/use-domain-apex-with-endpoints/aws-domain-apex-redirect"},{"title":"Domain Apex Redirect","description":null,"href":"/how-to-guides/app-guides/use-domain-apex-with-endpoints/domain-apex-redirect"}]},{"title":"How to use S3 to accept file uploads","href":"/how-to-guides/app-guides/use-s3-to-accept-file-uploads"},{"title":"How to use cron to run scheduled tasks","description":"Learn how to use cron to run and automate scheduled tasks on Aptible","href":"/how-to-guides/app-guides/use-cron-to-run-scheduled-tasks"},{"title":"How to serve static assets","href":"/how-to-guides/app-guides/serve-static-assets"},{"title":"How to establish client certificate authentication","href":"/how-to-guides/app-guides/establish-client-certificiate-auth"}]},{"group":"Database Guides","pages":[{"title":"All Database Guides","sidebarTitle":"Overview","href":"/how-to-guides/database-guides/overview"},{"title":"How to configure Aptible PostgreSQL Databases","href":"/how-to-guides/database-guides/configure-aptible-postgresql-databases"},{"title":"Deploying PgBouncer on Aptible","href":"/how-to-guides/database-guides/pgbouncer-connection-pooling"},{"title":"How to connect Fivetran with your Aptible databases","href":"/how-to-guides/database-guides/connect-fivetran-with-aptible-db"},{"title":"Replicate PostgreSQL to BigQuery with Datastream","href":"/how-to-guides/database-guides/replicate-postgresql-to-bigquery-datastream"},{"title":"How to scale databases","href":"/how-to-guides/database-guides/how-to-scale-databases"},{"title":"Automate Database migrations","href":"/how-to-guides/database-guides/automate-database-migrations"},{"title":"Upgrade PostgreSQL with logical replication","href":"/how-to-guides/database-guides/upgrade-postgresql"},{"title":"Dump and restore PostgreSQL","href":"/how-to-guides/database-guides/dump-restore-postgresql"},{"title":"Test a PostgreSQL Database's schema on a new version","href":"/how-to-guides/database-guides/test-schema-new-version"},{"title":"Dump and restore MySQL","href":"/how-to-guides/database-guides/dump-restore-mysql"},{"title":"Use mysqldump to test for upgrade incompatibilities","href":"/how-to-guides/database-guides/test-upgrade-incompatibiltiies"},{"title":"Upgrade MongoDB","href":"/how-to-guides/database-guides/upgrade-mongodb"},{"title":"Upgrade Redis","href":"/how-to-guides/database-guides/upgrade-redis"}]},{"group":"Observability Guides","pages":[{"title":"All Observability Guides","sidebarTitle":"Overview","href":"/how-to-guides/observability-guides/overview"},{"title":"How to access operation logs","href":"/how-to-guides/observability-guides/access-operation-logs"},{"title":"How to export Activity Reports","href":"/how-to-guides/observability-guides/export-activity-reports"},{"title":"How to set up Datadog APM","href":"/how-to-guides/observability-guides/setup-datadog-apm"},{"title":"How to collect database-specific metrics using the New Relic agent","href":"/how-to-guides/observability-guides/setup-newrelic-agent-database"},{"title":"How to set up application performance monitoring","href":"/how-to-guides/observability-guides/setup-application-performance-monitoring"},{"title":"Collect Prometheus Metrics from Apps","href":"/how-to-guides/observability-guides/collect-prometheus-metrics-from-apps"},{"title":"How to deploy and use Grafana","href":"/how-to-guides/observability-guides/deploy-use-grafana"},{"title":"How to set up a self-hosted Elasticsearch Log Drain with Logstash and Kibana (ELK)","href":"/how-to-guides/observability-guides/elk"},{"title":"How to set up Elasticsearch Log Rotation","href":"/how-to-guides/observability-guides/elasticsearch-log-rotation"},{"title":"How to set up a Papertrail Log Drain","href":"/how-to-guides/observability-guides/papertrail-log-drain"},{"title":"How to set up a self-hosted HTTPS Log Drain","href":"/how-to-guides/observability-guides/https-log-drain"},{"title":"How to set up Kibana on Aptible","href":"/how-to-guides/observability-guides/setup-kibana"}]},{"group":"Platform Guides","pages":[{"title":"Platform Guides","sidebarTitle":"Overview","href":"/how-to-guides/platform-guides/overview"},{"title":"Heroku to Aptible Migration Guide","href":"/how-to-guides/platform-guides/heroku-migration"},{"title":"Heroku Shield to Aptible Migration Guide","href":"/how-to-guides/platform-guides/heroku-shield-migration"},{"title":"MedStack to Aptible Migration Guide","sidebarTitle":"MedStack Migration Guide","href":"/how-to-guides/platform-guides/medstack-migration"},{"title":"How to achieve HIPAA compliance on Aptible","href":"/how-to-guides/platform-guides/hipaa-compliance"},{"title":"Interface Feature Availability Matrix Guide","href":"/reference/interface-feature"},{"title":"How to create and deprovison dedicated stacks","href":"/how-to-guides/platform-guides/create-deprovision-dedicated-stacks"},{"title":"How to create environments","href":"/how-to-guides/platform-guides/create-environment"},{"title":"How to delete environments","href":"/how-to-guides/platform-guides/delete-environment"},{"title":"How to deprovision resources","href":"/how-to-guides/platform-guides/deprovision-resources"},{"title":"How to migrate environments","href":"/how-to-guides/platform-guides/migrate-environments"},{"title":"How to navigate security questionnaires and audits","href":"/how-to-guides/platform-guides/navigate-security-questionnaire-audits"},{"title":"How to Recover Deleted Resources","href":"/how-to-guides/platform-guides/restore-resources"},{"title":"How to upgrade or downgrade my plan","href":"/how-to-guides/platform-guides/upgrade-downgrade-plan"},{"title":"How to set up Single Sign On (SSO)","href":"/how-to-guides/platform-guides/setup-sso"},{"title":"How to Set Up Single Sign-On (SSO) for Auth0","href":"/how-to-guides/platform-guides/setup-sso-auth0"},{"title":"Provisioning with Okta (SCIM)","href":"/how-to-guides/platform-guides/scim-okta-guide"},{"title":"Provisioning with Entra Identity (SCIM)","href":"/how-to-guides/platform-guides/scim-entra-guide"},{"title":"Best Practices Guide","href":"/how-to-guides/platform-guides/best-practices-guide"},{"title":"Advanced Best Practices Guide","href":"/how-to-guides/platform-guides/advanced-best-practices-guide"},{"title":"Image and Vulnerability Scanning","sidebarTitle":"Image Vulnerability Scanning","href":"/how-to-guides/platform-guides/image-vulnerability-scanning"},{"title":"How to request HITRUST Inhertiance","href":"/how-to-guides/platform-guides/navigate-hitrust"},{"title":"Business Continuity Guide","href":"/how-to-guides/platform-guides/minimize-downtown-outages"},{"title":"How to cancel my Aptible Account","href":"/how-to-guides/platform-guides/cancel-aptible-account"},{"title":"How to reset my Aptible 2FA","href":"/how-to-guides/platform-guides/reset-aptible-2fa"},{"title":"How to Re-invite Deleted Users","href":"/how-to-guides/platform-guides/re-inviting-deleted-users"}]}]},{"group":"Support \u0026 Troubleshooting","pages":[{"title":"Aptible Support","href":"/how-to-guides/troubleshooting/aptible-support"},{"group":"Common Errors \u0026 Issues","pages":[{"sidebarTitle":"Overview","title":"Common Errors and Issues","href":"/how-to-guides/troubleshooting/common-errors-issues/overview"},{"title":"Enabling HTTP Response Streaming","href":"/how-to-guides/troubleshooting/common-errors-issues/enabling-http-response"},{"title":"App Processing Requests Slowly","href":"/how-to-guides/troubleshooting/common-errors-issues/app-processing-requests-slowly"},{"title":"Application is Currently Unavailable","href":"/how-to-guides/troubleshooting/common-errors-issues/application-unavailable"},{"title":"before_release Commands Failed","href":"/how-to-guides/troubleshooting/common-errors-issues/before-released-commands-fail"},{"title":"Build Failed Error","href":"/how-to-guides/troubleshooting/common-errors-issues/build-failed-error"},{"title":"Container Failed to Start Error","href":"/how-to-guides/troubleshooting/common-errors-issues/container-failed-start-error"},{"title":"Deploys Take Too long","href":"/how-to-guides/troubleshooting/common-errors-issues/deploys-take-long"},{"title":"git Reference Error","href":"/how-to-guides/troubleshooting/common-errors-issues/git-reference-error"},{"title":"git Push \"Everything up-to-date.\"","href":"/how-to-guides/troubleshooting/common-errors-issues/git-push-everything-utd"},{"title":"HTTP Health Checks Failed","href":"/how-to-guides/troubleshooting/common-errors-issues/http-health-check-failed"},{"title":"App Logs Not Being Received","href":"/how-to-guides/troubleshooting/common-errors-issues/apps-logs-not-received"},{"title":"PostgreSQL Replica max_connections","href":"/how-to-guides/troubleshooting/common-errors-issues/postgresql-replica"},{"title":"Connecting to MongoDB fails","href":"/how-to-guides/troubleshooting/common-errors-issues/connecting-mongodb-fails"},{"title":"MySQL Access Denied","href":"/how-to-guides/troubleshooting/common-errors-issues/mysql-access-denied"},{"title":"No CMD or Procfile in Image","href":"/how-to-guides/troubleshooting/common-errors-issues/no-cmd-procfile-image"},{"title":"git Push Permission Denied","href":"/how-to-guides/troubleshooting/common-errors-issues/git-push-permission-denied"},{"title":"aptible ssh Permission Denied","href":"/how-to-guides/troubleshooting/common-errors-issues/aptible-ssh-permission-denied"},{"title":"PostgreSQL Incomplete Startup Packet","href":"/how-to-guides/troubleshooting/common-errors-issues/postgresql-incomplete"},{"title":"PostgreSQL SSL Off","href":"/how-to-guides/troubleshooting/common-errors-issues/postgresql-ssl-off"},{"title":"Private Key Must Match Certificate","href":"/how-to-guides/troubleshooting/common-errors-issues/private-key-match-certificate"},{"title":"aptible ssh Operation Timed Out","href":"/how-to-guides/troubleshooting/common-errors-issues/aptible-ssh-operation-timed-out"},{"title":"SSL error ERR_CERT_AUTHORITY_INVALID","href":"/how-to-guides/troubleshooting/common-errors-issues/ssl-error-auth-invalid"},{"title":"SSL error ERR_CERT_COMMON_NAME_INVALID","href":"/how-to-guides/troubleshooting/common-errors-issues/ssl-error-common-name-invalid"},{"title":"Unexpected Requests in App Logs","href":"/how-to-guides/troubleshooting/common-errors-issues/unexpected-requests-app-logs"},{"title":"Managing a Flood of Requests in Your App","href":"/how-to-guides/troubleshooting/common-errors-issues/unexpected-request-volume"},{"title":"Operation Restricted to Availability Zone(s)","href":"/how-to-guides/troubleshooting/common-errors-issues/operation-restricted-to-availability"}]}]}]}]},"basePath":"","title":"How to use S3 to accept file uploads - Aptible","buildId":"dpl_4RHMRqtvdHvKgaEfTTjFqjzja3B6","deploymentId":"dpl_4RHMRqtvdHvKgaEfTTjFqjzja3B6","dynamics":[],"chunks":[]}