Feature
Choose website file storage by how the application reads and writes
Choose filesystem or object storage for website assets, then define access, caching, retention and restore checks before moving files.
Impetuous · · 4 Min Read

A website’s images, PDFs and generated pages are all files. That does not mean they need a shared filesystem. The useful distinction is how the application accesses them: through operating-system paths or through an object API. Separately, decide which files belong in a deployment and which need to change independently.
For a publishing site, a proposed starting architecture is object storage for independently managed media, deployment artifacts for code and bundled assets, and persistent filesystem storage where the application needs filesystem behavior. Make that filesystem shared only when multiple application instances need access to it.
Choose the interface before the provider
Cloud file storage exposes files and directories to applications. For example, Amazon EFS provides shared access through NFSv4, allowing applications to use their operating system’s filesystem interface. Amazon S3’s object interface instead uses an API to store and retrieve objects. AWS’s EFS comparison explains this distinction.
| Website requirement | Starting choice | What to verify |
|---|---|---|
| A CMS or plugin reads and writes a shared uploads directory | Shared file storage, or a supported object-storage integration | Required filesystem operations and plugin compatibility |
| Images, PDFs and downloads are uploaded and retrieved by key | Object storage | Upload API, delivery URLs, permissions and metadata |
| Generated HTML, CSS and JavaScript ship together | Versioned deployment artifact | Complete release, routing and rollback behavior |
| A database needs persistent disk access | Database-supported persistent storage | The database’s storage and backup requirements—not just where media lives |
A deployment artifact is a release-packaging choice, not a separate storage protocol.
Do not infer filesystem compatibility from a console that displays “folders.” In S3, a key such as media/2026/chart.webp identifies an object; the slashes allow tools to infer a hierarchy, but the underlying object model is flat. S3’s naming documentation makes that explicit.
Before migrating a CMS, list its actual operations: reading whole files, appending, renaming, locking, generating thumbnails and deleting originals. Test those operations through the proposed storage integration. A successful upload alone is not a compatibility test.
Separate source files from public delivery
Use an explicit policy for each class of content:
- Editorial originals: retain privately as the source for regenerating derivatives.
- Published derivatives: make only the approved versions available through the website’s delivery path.
- Private exports and reports: keep outside the public media delivery path, with separate authorization.
- Temporary build files: make disposable only after confirming the retained inputs can reproduce them.
Separate buckets or storage resources can make these boundaries easier to enforce. Naming a prefix private/ is not an access policy.
Public delivery also need not mean a publicly readable origin bucket. On AWS, CloudFront origin access control can authorize a distribution to read a regular S3 bucket. It does not work with S3 website endpoints, which must be configured as custom origins. CloudFront’s origin-access documentation describes the requirements.
Keep viewer authorization separate from origin authorization: protecting the bucket from direct access does not, by itself, make a download private to a reader. CloudFront’s private-content workflow treats signed URLs or signed cookies and restrictions on direct origin access as separate controls.
Make asset replacement predictable
For public assets that can use a new URL when their contents change, adopt versioned or content-hashed names. A hypothetical replacement might change chart.a1b2.webp to chart.c3d4.webp, then update the page reference.
This supports long-lived caching without asking caches to discover that an existing URL now contains different bytes. MDN documents versioned URLs with long max-age and immutable as a cache-busting pattern. Use immutable only when the resource will not change while fresh. MDN’s Cache-Control reference also distinguishes no-cache, which requires revalidation before reuse, from no-store, which prevents storage.
For releases, upload the new assets before publishing pages that reference them. Retain assets needed by the previous release through the rollback window. Avoid deleting every file absent from the latest build unless the deletion process accounts for older pages and releases.
Define recovery and cost together
Versioning helps recover from overwrites and accidental deletion, but retention still needs a policy. In S3, versioning is disabled by default; each retained version is a full object, not a diff. Lifecycle rules for noncurrent versions determine when those older versions are permanently removed. S3’s versioning documentation covers both recovery behavior and storage charges.
Specify which originals must survive, how long releases remain recoverable, who can permanently delete versions, and where a recovery copy is protected from routine publishing credentials.
Budget beyond stored gigabytes. S3’s cost components include requests, retrieval, transfer, management and replication—not storage alone. Its pricing page lists these categories. Estimate the actual workload: uploads, derivative generation, origin reads, downloads and retained versions.
Test the storage policy before switching
Run a small end-to-end check:
- Upload an original and generate a derivative.
- Publish it and inspect the delivered content type and cache headers.
- Confirm requests without authorization cannot retrieve private files through either origin or delivery URLs.
- Replace the asset, then roll back the page and verify its previous reference still works.
- Restore a deliberately deleted test object using the documented recovery procedure.
Keep the storage role, delivery role and recovery owner in the site’s infrastructure dependency map. The decision is complete when publishing, access control and restoration work—not when the storage resource has been created.