sehaj/learn
System design/09 Storage under the hood

09.04 · concept · 12 min

How object storage works

Where files, images, exports and archives go: object storage like S3. The model (buckets, keys, whole immutable objects), why it scales where file systems and databases don't, and how such a system is built underneath: metadata, packed storage, spreading data over many disks.

The problem: bytes that don't belong in a database

Snip now produces three kinds of file:

  • QR code images for every paid link, about 5 KB each, millions of them, fetched by browsers.
  • CSV exports of an owner's click history, from kilobytes to several gigabytes.
  • Archived click history, compressed monthly files kept for years, rarely read.

Postgres could hold them as large values, but it would bloat backups, replication and the buffer cache with data that doesn't need transactions or indexes. A shared file system on the app servers doesn't scale past a few machines and is one more thing to keep available. This is what object storage is for: Amazon S3, Google Cloud Storage, Azure Blob Storage, or self-hosted MinIO and Ceph.

The model

  • Buckets hold objects. Each object has a key (qr/x7Kp.png, exports/4821/2026-11.csv), its bytes, and a little metadata (content type, custom tags).
  • The namespace is flat. The slashes in keys look like folders, but there are no directories; listing by prefix just filters keys.
  • Objects are written and read whole. You can read a byte range, but you can't change byte 1,000 of an object; you replace the object. That immutability is what makes the system simple to replicate, cache and scale.
  • Operations are few: PUT, GET, DELETE, LIST by prefix, plus multipart upload for big objects (upload parts in parallel, retry failed parts, then combine) and pre-signed URLs, which let a browser upload or download directly without passing through your servers (13.05 Signed URLs and access control).

On S3 today, reads after a successful write, overwrite or delete always return the latest version, including LIST (08.02 Consistency models).

How it's built underneath

The systems differ, but the shape is common:

  1. A front end authenticates the request and finds where the object lives.
  2. A metadata service maps each key to its location: which storage nodes, which files, which offsets. It's a huge, partitioned key-value store in its own right (05.03 Consistent hashing).
  3. Storage nodes hold the bytes, usually split into pieces with redundancy across machines, racks and data centres, either by replication or erasure coding (09.05 Replication vs erasure coding).

Small objects: don't use a file per object

The naive design stores each object as a file on a storage node's file system. With billions of small files, the problem isn't data; it's file-system metadata. Finding a file's blocks means reading its inode and directory entries, often from disk, before reading the data. Facebook's photo store hit exactly this: reading metadata became the throughput bottleneck.

Their answer, Haystack, packs many photos ("needles") into a few huge append-only files, and keeps a compact in-memory index from photo ID to file offset: the log-and-index design from 09.01 A storage engine is a log and an index, so a read needs at most one disk operation. Modern object stores pack small objects into large files in a similar spirit.

Spreading the load

A hard disk does only about a hundred random operations a second, so the key to performance at scale is spreading each customer's data over very many drives, so no single disk gets hot. Andy Warfield, describing S3, calls this "heat management": objects are deliberately placed on different sets of drives, so each customer's requests are spread over a very large number of disks, and S3 has tens of thousands of customers whose buckets span millions of drives.

Snip's files in object storage
GET qr/x7Kp.pngon missexport pleasemultipart PUTpre-signed GETBrowserCDNQR imagesSnip appsigns URLsObject storeqr/, exports/Export workerwrites CSVs

4 steps. Use Next and Back to follow the request.

Text version
  1. QR images are public and never change, so browsers fetch them through the CDN, which fetches from the object store on a miss (02.05).
  2. An owner asks for an export. The app queues a job (07.05) instead of building a 2 GB file in a request.
  3. The export worker streams the CSV into the object store as a multipart upload: parts in parallel, each retried on its own.
  4. The owner downloads it directly from the store with a short-lived pre-signed URL; the bytes never pass through Snip's servers.
  • Browser → CDN: GET qr/x7Kp.png
  • CDN → Object store: on miss
  • Browser → Snip app: export please
  • Export worker → Object store: multipart PUT
  • Browser → Object store: pre-signed GET

Storage classes and lifecycle

Object stores price by how often you read. Snip's archives move automatically, by lifecycle rules on their key prefix, from the standard class to an infrequent-access class after 30 days and to an archive class after a year: cheaper to keep, slower and costlier to read. Exports are deleted after 30 days.

Seen in production

Amazon

2023

S3

Based on his USENIX FAST '23 keynote, Warfield describes S3 as built from millions of hard disks, each able to do only about 120 operations a second. Objects are split with an algorithm such as Reed-Solomon into k shards plus m parity shards, and can be read as long as k of them are available. S3 calls the problem of keeping load even "heat management", and intentionally places different objects on different sets of drives so each customer's accesses are spread over a very large number of disks. The lowest storage layer on each disk, ShardStore, was rewritten in Rust.

What we foundMillions of hard disks, erasure-coded shards, and deliberate spreading of data so no drive gets hot.

Building and operating a pretty big storage system called S3 (Andy Warfield, All Things Distributed)allthingsdistributed.com ↗

Facebook

2010

Haystack

At the time, Facebook stored over 260 billion images, more than 20 petabytes, with users uploading a billion new photos (about 60 TB) a week and over a million images served per second at peak. With a network file system, each file's metadata had to be read from disk before the file, which became the throughput bottleneck. Haystack keeps all metadata in main memory, made practical by drastically shrinking the metadata needed per photo, so a read needs at most one disk operation.

What we foundWith billions of small files, file-system metadata becomes the bottleneck; pack objects into big files and keep the index in memory.

Finding a needle in Haystack: Facebook's photo storage (OSDI 2010)usenix.org ↗
Predict first

Snip stores each QR image as its own file on a shared network file system. At 300 million images, reads are slow even though the disks are mostly idle. What's the likely bottleneck?

Commit to an answer before you read on.

Recap

Interview questions

SeniorfreqGood to knowDesign

How would you design an object storage service like S3?

Report a mistakeEdit this page