Part 3 · The Building Blocks

Object Storage: How S3-Style Storage Works

Images saved to a server's disk vanish when you add a second server. How S3-style object storage keeps files safe at any scale, why uploads should skip your servers entirely, and what belongs in the database instead.

Lesson 177 min readbeginner#storage#s3

On this page

  1. The Problem
  2. The Core Idea
  3. How It Works
  4. Trade-offs
  5. In the Real World
  6. Interview Questions
  7. Key Takeaways
  8. Further Reading

The Problem

Your app lets users upload profile pictures, and you save them to the server's disk in /uploads. Then:

  • You add a second server (post 7). Half the images now "disappear", because they're on the other machine's disk.
  • The disk fills up.
  • A server dies and takes a year of uploads with it.
  • Someone suggests "just put the images in the database as BLOBs" (a BLOB, or binary large object, is a column that holds raw file bytes), and your database backups go from 5 GB to 500 GB.

Images, videos, PDFs, backups and logs need a different kind of storage: object storage, the kind made famous by Amazon S3.

Object storage is a service that stores whole files as separate objects, each found by a name, and that grows to almost any size. You use it over HTTP (the protocol of the web). Amazon S3 (Simple Storage Service) is the best-known example.

The Core Idea

Think of a cloakroom at a big event or a railway station.

  • You hand over your bag and get a ticket number.
  • You don't care which shelf it's on, or how the room is organised.
  • Later, you show the ticket and get your bag back.
  • The cloakroom can hold millions of bags, and staff keep copies of the records so nothing gets lost.

Object storage works the same way:

  • You store a file (the object) with a name (the key) inside a bucket.
  • You get it back later by its key, over HTTP.
  • The service handles where it lives, copying it for safety, and growing without limit. A bucket is like a top-level folder that holds your objects. A key is the unique name of one object inside it.

How It Works

Three kinds of storage

Block storage works like a disk that one server reads and writes in small blocks. File storage works like a shared folder. Object storage works like a huge key-to-file store. In the table, EBS, NFS and EFS are block and file services (Amazon Elastic Block Store, the Network File System, and Amazon Elastic File System). A data lake is a large store of raw data kept for later analysis.

TypeThink of it asExampleGood for
Block storageA raw hard drive attached to one serverAWS EBS, a local SSDDatabases, operating system disks
File storageA shared network folder with directoriesNFS, AWS EFSShared files between servers, legacy apps
Object storageA giant key → file store accessed over HTTPAmazon S3, Google Cloud Storage, Azure Blob, Cloudflare R2, MinIOImages, videos, backups, logs, static sites, data lakes

The object model

  • Bucket: a top-level container, like myapp-user-uploads.
  • Key: the object's name, like users/42/avatar.jpg.
  • Object: the data (from a few bytes up to many terabytes) plus metadata (information about the data, such as content type, size and custom tags).

There are no real folders. users/42/avatar.jpg is just a key that happens to contain slashes. Tools show it like folders by grouping keys with the same prefix (the first part of the key, such as users/42/).

You work with objects through a simple HTTP API (a set of web requests). PUT means save, GET means read and DELETE means remove:

HTTP
PUT    /myapp-user-uploads/users/42/avatar.jpg     (upload)GET    /myapp-user-uploads/users/42/avatar.jpg     (download)DELETE /myapp-user-uploads/users/42/avatar.jpg     (delete)GET    /myapp-user-uploads?prefix=users/42/        (list keys)

Objects are usually replaced whole, not edited in place. To change one byte of a video, you upload the whole object again (or a new version).

Why it's so durable

Durability is the chance that your data is not lost over time. Object stores are designed so data is almost never lost:

  • Each object is stored on many disks, in multiple data centres. An availability zone is one separate data centre (or group of them) inside a cloud region, with its own power and network.
  • Many systems use erasure coding: data is split into pieces plus extra "parity" pieces, so the original can be rebuilt even if several pieces are lost. It's a bit like being able to finish a jigsaw even with a few pieces missing. It uses less space than keeping three full copies.
  • Background processes constantly check for damaged copies and repair them.

Amazon S3 is designed for 99.999999999% durability ("eleven nines"). In practice, you're far more likely to lose data by deleting it yourself than through S3 losing it. That's why versioning and backups still matter.

Consistency

Consistency describes whether every reader sees the latest data. Since December 2020, Amazon S3 provides strong read-after-write consistency: after a successful upload or overwrite, any read gets the new version. Before that, you could sometimes read an old version shortly after updating. Other providers offer similar guarantees today, but check the documentation of the one you use.

Uploads and downloads without your servers

A key pattern: don't send file bytes through your app servers. Instead, use pre-signed URLs. A pre-signed URL is a temporary web link, signed by your server, that lets a client upload or download one specific object directly. The signature proves your server allowed it.

step 1 / 7
Browser
Your API
Object storage
Database
  1. I want to upload avatar.jpg
  2. ↻ check user may upload; sign a PUT URL, valid 5 min
  3. pre-signed URL
  4. PUT users/42/avatar.jpg
    2 MB, straight to storage
  5. 200 OK
  6. upload done
    or storage emits an event
  7. user 42 avatar = users/42/avatar.jpg
Direct upload with a pre-signed URL. The file bytes never pass through your servers. · sequence · step through

The benefits:

  • Your servers never handle heavy file traffic, so they stay small and fast.
  • Uploads scale with the storage service, not with your app.
  • Files stay private. Only people with a valid, short-lived link can access them.

For large files, use multipart upload: split the file into parts (say 10 MB each), upload them in parallel (at the same time), and retry only failed parts. For video playback, clients can use range requests (HTTP requests that ask for only a byte range of a file) to download just the part they need.

Serving files to users

For public content (product images, avatars), put a CDN in front of the bucket (post 14). A CDN is a group of servers around the world that keep copies of files close to users. Users get fast, nearby copies, and you pay less for bandwidth. For private content, give out pre-signed download URLs, or have the CDN check access.

What goes in the database vs object storage

  • Object storage: the file itself. users/42/avatar.jpg is 2 MB.
  • Database: the metadata. Who owns it, the key, size, type, upload time, maybe a thumbnail key.
Diagram
photos table
┌────┬─────────┬───────────────────────────────┬────────┬─────────────┐
│ id │ user_id │ storage_key                   │ size   │ uploaded_at │
├────┼─────────┼───────────────────────────────┼────────┼─────────────┤
│ 17 │ 42      │ users/42/photos/17-orig.jpg   │ 2.1 MB │ 2026-11-01  │
└────┴─────────┴───────────────────────────────┴────────┴─────────────┘

Why not store images as BLOBs in the database?

  • They make the database huge, backups slow, and replicas expensive.
  • They waste the database's precious memory and I/O (reading and writing the disk) on data that doesn't need queries or transactions (groups of changes that succeed or fail together).
  • Object storage is much cheaper per GB and built for exactly this.

Storage classes and lifecycle rules

Not all files are used equally. Object stores offer storage classes at different prices:

  • Standard: frequently accessed. Higher storage price, cheap to read.
  • Infrequent access: cheaper storage, but a fee each time you read.
  • Archive (like S3 Glacier): very cheap storage, but retrieval can take minutes to hours (some archive classes are faster).

Lifecycle rules are rules you set that move or delete objects automatically. For example: "move logs to infrequent access after 30 days, to archive after 90 days, and delete after 7 years". This can cut storage bills a lot.

Other useful features

  • Versioning: keep old versions when objects are overwritten or deleted. It protects against accidents.
  • Event notifications: a message such as "a new object was uploaded", which triggers a function or queue to create thumbnails, scan for viruses or transcode videos (convert them to other formats and sizes).
  • Encryption at rest: the stored data is scrambled so it is unreadable without a key. This is usually on by default.
  • Access policies: control who can read and write each bucket.

How an S3-like system is built (simplified)

Diagram
          ┌──────────────────┐
Client ──►│  API / front end │  auth, routing
          └───┬─────────┬────┘
              ▼         ▼
   ┌────────────────┐  ┌──────────────────────┐
   │ Metadata store │  │   Data nodes         │
   │ key → location │  │ (disks storing       │
   │ size, version  │  │  object pieces,      │
   └────────────────┘  │  replicated/erasure- │
                       │  coded across zones) │
                       └──────────────────────┘
  • The metadata service (the part that stores information about objects) is like a giant index: "users/42/avatar.jpg is stored as pieces on nodes 17, 203 and 881".
  • The data nodes store the actual bytes.
  • Separating them lets each scale independently, which is the same design idea behind many large storage systems.
Block storage
  • •A raw disk attached to one server
  • +Lowest latency; random reads and writes
  • −One machine at a time
Use whenDatabase files, OS disks (AWS EBS)
File storage
  • •A shared network folder
  • +Many servers, normal file paths
  • −Harder to scale; slower metadata
Use whenShared files, legacy apps (NFS, EFS)
Object storage
  • •Key → object over HTTP
  • +Unlimited scale, 11 nines durability, cheap per GB
  • −Tens to hundreds of ms per request; replace whole objects
Use whenImages, video, backups, logs, data lakes (S3)
Three kinds of storage, three jobs. · compare
  1. 1
    Standard
    days 0–30 — read often, cheap to read
  2. 2
    Infrequent access
    days 30–90 — cheaper to store, fee per read
  3. 3
    Archive (Glacier)
    90 days → 7 years — pennies per GB, hours to retrieve
  4. 4
    Delete
    after 7 years, by rule
Lifecycle rules move data to cheaper classes as it cools, automatically. · flow

Trade-offs

  • ✅ Virtually unlimited scale, very high durability, and a low cost per GB.
  • ✅ A simple HTTP API, and it works well with CDNs.
  • ❌ Higher latency than a local disk (tens to a few hundred milliseconds per request), so it's not for database files.
  • ❌ No partial updates. You replace objects whole.
  • ❌ Not a file system. Listing millions of keys or renaming "folders" is slow and awkward.
  • ❌ Costs can surprise you: data transfer out (egress: data leaving the provider's network), per-request charges, and retrieval fees for archive classes.
  • ❌ Misconfigured public buckets are a common cause of data leaks. Keep buckets private by default.

In the Real World

Amazon S3 launched in 2006 and became one of the foundations of cloud computing. Its API is now a de facto standard. Many other products (Google Cloud Storage, Cloudflare R2, MinIO, Backblaze B2 and others) offer S3-compatible APIs, so the same code works with them.

Dropbox's Magic Pocket. Dropbox originally stored users' files on Amazon S3. Around 2015 to 2016 it moved most of that data to its own custom storage system, Magic Pocket, to save costs and gain control at its scale. It's a good example of "build vs buy" changing as a company grows.

Facebook's Haystack. Facebook designed a special photo storage system called Haystack, because storing billions of small photos as individual files on regular file systems wasted time on metadata lookups. Its paper (OSDI 2010) is a classic on designing storage for many small objects.

Everyday apps. When you upload a photo to a messaging or social app, it usually goes (often via a pre-signed URL) to object storage. An event triggers resizing into several sizes, and the app shows it back to you through a CDN. This is the exact flow described above.

Data leaks from public buckets. There have been many news stories about companies accidentally exposing private files by making storage buckets public. That's why modern cloud providers block public access by default and show warnings when you change it.

Interview Questions

Q1Why not store user-uploaded images in the database?

They bloat the database, slow backups and replicas, and waste the database's memory and I/O on bytes that never need queries or transactions. Object storage is far cheaper per GB and built for it; the database keeps only metadata and the object key.

Q2How would you design file uploads for a mobile app?

The app asks the API for a pre-signed PUT URL (after an authorisation check), uploads directly to object storage — multipart for large files — then confirms. A storage event triggers workers for thumbnails, virus scanning or transcoding, and files are served through a CDN.

Q3What makes object storage so durable?

Each object is stored redundantly across many disks in several availability zones, often with erasure coding (data plus parity pieces), and background processes continuously detect and repair damaged pieces. S3 is designed for 11 nines of durability — your own deletes are the bigger risk, hence versioning.

Q4What are pre-signed URLs, and why are they safe?

Time-limited URLs signed with your credentials that grant one operation on one object. The bucket stays private; your API decides who gets a link, and it expires within minutes.

Q5Where do object-storage costs surprise people?

Egress (data transferred out), per-request charges on many small objects, and retrieval fees and delays for archive classes. A CDN in front and lifecycle rules usually help most.

Key Takeaways

  • Object storage keeps files as objects in buckets, addressed by keys over HTTP. It's built for huge scale and high durability.
  • Store files in object storage and metadata in the database. Don't put large files in your database.
  • Use pre-signed URLs so clients upload and download directly, not through your servers. Use multipart upload for big files.
  • Put a CDN in front for fast delivery, and use storage classes and lifecycle rules to control cost.
  • Keep buckets private by default, enable versioning for important data, and watch egress costs.

Further Reading

  • The Amazon S3 User Guide (official documentation)
  • System Design Interview Volume 2 by Alex Xu and Sahn Lam (chapter "S3-like Object Storage")
  • The paper "Finding a needle in Haystack: Facebook's photo storage" (OSDI 2010)
  • Werner Vogels' article on S3 strong consistency ("Diving Deep on S3 Consistency")
  • The MinIO documentation (an open-source S3-compatible object store you can run locally)

Published by Jainik · Last updated · How these lessons are made

Keep learning

Related series