File Storage Solutions: S3, CDN and Backups

File storage solutions decide where uploads, product images, invoices and backups live once they no longer fit comfortably on the web server’s disk. A shop that keeps every photo in wp-content/uploads works until the disk fills, a deploy wipes the files, or a second server has nothing to serve. Customers see broken images. You see a restore that nobody has ever tested.

At CodeWiz we move files to object storage, put a CDN in front of what is public, and keep backups that can actually be restored. The usual targets are AWS S3 and Google Cloud Storage, sometimes an S3-compatible bucket when the egress bill is the real problem. The application keeps a database. The bucket keeps the bytes.

This is for online shops, media-heavy sites, apps that accept user uploads, and any team that has already lost a folder of files or is afraid to. If deploys are scary because the server disk holds state, storage is the piece to separate first.

File Storage Solutions on AWS S3

Amazon S3 is our default file storage solution when you want a durable bucket, a huge ecosystem and libraries in every language we ship. Files are objects addressed by a key, not files in a directory tree. That sounds like a detail. It changes backups, deploys and how many servers can serve the same uploads.

How we set a bucket up

  • A bucket in a region close to the application, with Block Public Access left on. Public files are published through the CDN, not by opening the bucket.
  • A dedicated IAM user or role that can touch only that bucket, with separate credentials for production and staging.
  • Versioning, so an overwrite or a bad delete can be undone, and a lifecycle rule that expires old versions and incomplete multipart uploads.
  • Server-side encryption, and access logs or CloudTrail data events where you need to know who read a sensitive object.
  • The application configured to stream uploads straight to S3. WordPress, Laravel and Node.js all have well-worn adapters. Local disk stops being the source of truth.

A short lifecycle rule is usually the difference between a tidy bucket and a bill that grows forever:

{ "Rules": [{ "ID": "expire-old-versions", "Status": "Enabled", "Filter": { "Prefix": "" }, "NoncurrentVersionExpiration": { "NoncurrentDays": 30 }, "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 } }] }

The AWS S3 user guide covers the API. What we hand over is the bucket, the policy, the application change, and a note of which prefixes are public, private or temporary.

Rows of books on library shelves, a stand-in for organized file storage

Google Cloud Storage When You Are Already on Google

Google Cloud Storage does the same job as S3: durable objects, signed access, lifecycle rules and a CDN in front. We choose it when the rest of the system is already on Google, when a client standardises on one cloud, or when a specific GCS feature is the reason. We do not run two object stores for pride.

What changes compared with S3

  • Identity is IAM on Google Cloud, not an AWS access key. Workload identity or a tightly scoped service account replaces a long-lived key wherever the platform allows it.
  • Storage classes (Standard, Nearline, Coldline, Archive) map onto how soon you need the bytes back. Invoices from three years ago do not need Standard.
  • Uniform bucket-level access is turned on, so object ACLs cannot quietly contradict the bucket policy.
  • The application adapter changes. The idea does not: the database stores the object key, the bucket stores the bytes, and a deleted server does not delete the files.

Google’s Cloud Storage documentation is the reference for classes and signed URLs. If you are choosing between the two with no existing commitment, we usually start on S3 or on Cloudflare R2 when egress is the dominant cost, and we say so before any bucket is created.

Disk, Object Storage or Both

Object storage is not a reflex. A five-page site with four photos does not need a bucket. A database must not be “just put on S3” as its live data directory. The split is about what has to be local and what is a blob.

PlaceGood forPricing shapeWatch out for
Server diskThe application, small sites, a databaseIncluded in the VPSDies with the disk. Deploys can wipe it
AWS S3Uploads, media, exports, most appsStorage, requests and egressEgress and a chatty app can dominate the bill
Google Cloud StorageThe same, inside Google CloudStorage class plus operationsA different identity model to learn
S3-compatible (R2 and others)Public media where egress is expensiveOften no egress fee to the internetCheck the features your code actually calls

A pattern we use often: the database and the app stay on the server or a managed database, public media goes to a bucket behind the CDN, and private documents go to a second prefix that is never cached. Moving an existing uploads folder is a bulk copy, a code change, then a period where both locations are read until we are sure nothing still points at the disk.

Ethernet cable in focus in front of a blurred coil of network cables

CDN Configuration in Front of the Files

A bucket in one region is durable. It is not fast for a visitor on another continent, and it should not be the hostname in your HTML. The CDN is what makes file storage solutions feel like part of the site: a custom domain, cache and HTTPS, with the bucket hidden behind it.

What we configure

  • A hostname such as media.example.com on Cloudflare, pointed at the bucket, with the bucket itself refusing anonymous requests from anywhere else.
  • Long cache lifetimes for files whose names change when the content changes (hash or unique id in the key), and short ones for anything that gets overwritten in place.
  • Image variants and compression at the edge where they help, without caching HTML that belongs to a logged-in user.
  • Hotlink and abuse limits, so a popular file cannot become an open proxy for someone else’s bandwidth.

Private files never go through a public cache. A signed URL, valid for minutes, is the right tool for an invoice or a customer download. We have described the edge settings in more depth in our guide to professional Cloudflare configuration, and a practical upload API in our PHP CDN uploader.

Who Can Read a File: Public, Private and Signed

The mistake that hurts is treating every upload as public because that was easier on day one. Product photos are public. ID scans, invoices and exports are not. We split them on purpose.

  • Public media lives under a prefix the CDN may cache. Keys are unguessable or content-addressed. Listing the bucket is disabled.
  • Private documents stay in a prefix with no public policy. The application checks the user, then issues a signed URL that expires.
  • Temporary uploads land in a prefix with a lifecycle rule of a day or two, so abandoned files do not accumulate.
  • Cross-account access uses a bucket policy for a specific role, not a shared access key pasted into a chat.

Signed URLs are short. An hour is already generous for a download link in an email. A URL that works next year is just a public file with extra steps.

Orange Ethernet plug close-up against a plain light background

Backup Strategies That Survive a Bad Day

Object storage is durable against a disk dying. It is not a backup against a bug that deletes the wrong prefix, a leaked key, or an account you can no longer log into. Backups are a second copy, in a second place, that you have restored at least once.

What we actually set up

  • Versioning and a retention lock on buckets that hold data you cannot recreate, so a delete does not become permanent for a defined number of days.
  • A copy in another region or another provider for the data that would stop the business: database dumps and the private document prefix. Public media can often be rebuilt, and we say so rather than copying it blindly.
  • Database dumps on a schedule written to the bucket, encrypted, with a lifecycle that matches how far back you would really roll.
  • A restore drill. We pick a file and a database backup and bring them back onto a clean machine. A backup that has never been restored is a hope.

For shops, the painful loss is not always the photos. It is an order that existed only in a session or a log. We have written about keeping every order recoverable in zero data loss e-commerce. File backups and that kind of capture solve different problems, and a serious shop needs both.

Moving Existing Uploads Without Breaking URLs

Most file storage solutions we deliver are a move, not a green field. Years of files sit on one server, and the HTML, the database and outside sites all point at those URLs.

  1. Inventory the folders, the total size and which paths are public.
  2. Copy to the bucket in the background. Repeat until the daily delta is small.
  3. Point new uploads at the bucket, and keep reading old files from disk until the copy has caught up.
  4. Switch reads to the bucket. Put redirects or a CDN rule on the old URLs so links already in Google and in old emails still work.
  5. Leave the disk copy in place for a while. Delete it only after logs show nobody is reading it.

We do this for WordPress and WooCommerce, Laravel, and custom Node.js apps. The database stores keys. The theme or the API generates the public URL. Hard-coded /uploads/2024/... paths get a pass with a script, not a hope that search-and-replace in the database was enough.

Common File Storage Mistakes

  • A public bucket, or a policy with Principal: "*" left over from a tutorial.
  • Access keys in the Git repository, or one key shared by production, staging and a freelancer’s laptop.
  • Uploads still written to local disk “just for now”, so the next deploy or the second server does not have them.
  • No lifecycle rule, so incomplete uploads and old versions grow for years.
  • Private PDFs cached on the CDN, or signed URLs that expire in a decade.
  • Backups on the same disk as the site, and a restore that has never been tried.

What File Storage Solutions Cost

We estimate after looking at how many files you have, how large they are and who downloads them. The storage line on the invoice is often the small one.

  • Egress. Every gigabyte served from the bucket to the internet is billed, unless you chose a store that does not charge it. A CDN cache in front cuts that, it does not remove the need to look.
  • Requests. A page that asks for hundreds of tiny objects, or a script that lists the whole bucket, can cost more than the gigabytes.
  • Where the files are now. Moving a few gigabytes is an afternoon. Moving terabytes, with URL rewrites and a careful cutover, is a project.
  • How private the data is. Public product images are simpler than signed access, encryption and a second copy in another account.

Provider choice is part of the same conversation. We have laid out how we place workloads across clouds in our multi-cloud deployment guide. A bucket on the wrong continent, or egress you did not model, will dominate the monthly cost long after the setup is done.

How We Work

  1. Discovery: where files live today, how large they are, which are public, and what a lost disk would actually cost you.
  2. Plan: bucket, region, CDN hostname, private versus public prefixes, and how far back backups must go.
  3. Build: the bucket, the keys, the application adapter, the CDN and the lifecycle rules.
  4. Move: a background copy, then new uploads to the bucket, then reads, with the old URLs still answering.
  5. Prove: a restore of a file and a database dump, and a check that private objects are not cacheable.
  6. Hand over: a short note of prefixes, who holds the keys, and what the monthly bill should look like.

Why CodeWiz

  • We build the apps that store the files. WordPress, Laravel, Node.js and shops, so the adapter matches how the code really saves an upload.
  • Open-source first. Standard S3 APIs and open libraries, so you are not stuck with a panel’s private disk.
  • Right-sized. A small site keeps its files on disk if a bucket would only add cost and moving parts.
  • Performance and durability together. CDN, backups and the application are one piece of work. More about CodeWiz.
  • Fair pricing. Founded in Banja Luka in 2023, working remotely with clients locally and internationally. Premium work without premium prices.

Frequently Asked Questions

How much do file storage solutions cost?

Moving one site’s uploads to a bucket and a CDN is a small project. Terabytes, private documents and a careful URL migration take longer. You get an estimate after we see the volume and the application. The monthly storage bill is usually modest. Egress and request volume are what we check before promising that.

Should I use AWS S3 or Google Cloud Storage?

Use the one your application and your team already sit next to. If you are starting clean, S3 is the path with the most libraries, and an S3-compatible bucket is worth a look when bandwidth is the expensive part. We will not put you on both.

Is a bucket a backup?

No. A bucket survives a dead disk. It does not survive a delete, a bad deploy or a lost account, unless you have versioning, a second copy and a restore you have actually done. We set those up and run the restore once before we call it a backup.

Will my old image URLs keep working?

Yes, if we plan for them. New files get bucket URLs through the CDN. Old paths get a redirect or a CDN rule so links in Google, emails and other sites do not break. We only remove the disk copy after logs show it is idle.

Can you store files for WordPress or WooCommerce?

Yes. Media and product images move off wp-content/uploads onto the bucket, and the site keeps generating the right URLs. The database and the WordPress core stay on the server, where they belong.

Where should private customer documents live?

In a prefix that is not public and not cached, served only through a short-lived signed URL after your application has checked the user. Encryption and a second copy apply when losing those files would hurt.

Ready to Move Files Off the Server Disk?

Tell us where uploads live today and what you are afraid of losing. We will propose a bucket, a CDN hostname and a backup you can restore. Contact us to start, or see our file storage services.