Lesson 28 of 129
Object and Blob Storage
Object storage stores data as immutable objects in a flat namespace, each addressed by a key and accompanied by metadata, and accessed through an HTTP API. It is the storage model behind Amazon S3, Google Cloud Storage, and Azure Blob Storage. It is designed for very large volumes of unstructured data: images, videos, backups, logs, and data-lake files.
Block, file, and object storage
| Aspect | Block storage | File storage | Object storage |
|---|---|---|---|
| Unit | fixed-size block addressed by number | file in a directory tree | object addressed by key |
| Interface | read/write blocks (SCSI, NVMe, iSCSI) | POSIX or NFS/SMB: open, seek, write, rename | HTTP: PUT, GET, DELETE, LIST |
| Update in place | yes, any block | yes, any byte range | no; an object is replaced as a whole |
| Metadata | none (the file system above adds it) | fixed attributes (size, mtime, permissions) | rich, user-defined key-value metadata |
| Namespace | volume | hierarchical | flat (prefixes emulate folders) |
| Latency | lowest | low | highest of the three (each request is an HTTP call through front end and metadata lookup) |
| Scale | volume size limits | file server limits | practically unbounded |
| Typical use | databases, VM disks | shared home directories, legacy apps | media, backups, data lakes, static assets |
Object stores trade in-place mutation and low latency for scale, durability, and low cost per byte. A database should not be placed on an object store directly, but object stores hold database backups and are the base for many analytics engines.
Object model
- A bucket is a top-level container that has a globally unique name and holds configuration: access policy, region, lifecycle rules, encryption.
- An object is bytes plus metadata, identified by
(bucket, key). Keys such asphotos/2026/09/img1.jpglook like paths, but the namespace is flat. The/is a delimiter thatLISTcan use to group results as prefixes. - Operations:
PUT,GET(optionally with a byte range),DELETE,HEAD(metadata only),LISTby prefix. - Objects are immutable. Updating means writing a new object under the same key. With versioning enabled, older versions are retained and a delete adds a marker.
- Access uses per-object or per-bucket policies, and temporary pre-signed URLs that let a client upload or download one object directly without holding credentials.
Architecture
An object store separates the metadata path from the data path.
flowchart TB
Client --> FE["Front-end / API servers: auth, routing, request parsing"]
FE --> MS["Metadata service: key to chunk locations, versions, ACLs"]
FE --> PL["Placement service: choose storage nodes"]
FE --> DN1["Storage node 1"]
FE --> DN2["Storage node 2"]
FE --> DN3["Storage node 3"]
MS --> MDB[("Partitioned metadata database")]
DN1 --- RP["Background: repair, scrubbing, garbage collection"]
DN2 --- RP
DN3 --- RPFront end. Stateless servers behind a load balancer authenticate the request, check policy, and coordinate the read or write.
Metadata service. Maps (bucket, key, version) to object attributes and the list of chunks with their storage locations. It is a partitioned, replicated database sharded by bucket and key (see sharding and partitioning). Ordered storage is needed to serve LIST by prefix efficiently. Metadata is small relative to data but receives most operations, so it is often the scaling bottleneck of the system.
Data store. Many storage nodes hold the bytes on local disks. A placement service chooses nodes, spreading replicas or fragments across failure domains: disks, servers, racks, and availability zones.
Write path
- The client sends
PUTwith the object. - The front end splits the data into chunks if it is large.
- Each chunk is written to several nodes (replicas or erasure-coded fragments).
- After the required number of nodes acknowledge, the front end writes the metadata record.
- The metadata commit makes the object visible. The client receives success.
Ordering matters: data is written before metadata, so a failure in between leaves orphaned chunks that garbage collection removes, but never a metadata record pointing to missing data.
Read path
The front end looks up the metadata, then fetches the chunks from a healthy node (for byte-range reads, only the needed chunks) and streams them to the client.
sequenceDiagram
participant C as Client
participant F as Front end
participant M as Metadata service
participant D as Storage nodes
C->>F: GET /bucket/photos/img1.jpg
F->>M: lookup key
M-->>F: chunk list and node locations
F->>D: read chunks
D-->>F: chunk data
F-->>C: object bytesChunking
Large objects are divided into chunks (also called parts, extents, or blocks) of a fixed or bounded size, typically megabytes. Chunking:
- Lets one object spread across many nodes and be read in parallel.
- Bounds the unit of replication and repair.
- Enables range reads and resumable transfers.
- Enables deduplication when chunks are addressed by content hash, in systems that choose to do so.
Very small objects are inefficient with per-chunk overhead, so some designs pack many small objects into larger container files (Facebook's Haystack does this for photos to reduce metadata operations).
Durability: replication vs erasure coding
Durability is the probability that stored data is not lost over a period. Object stores advertise very high figures (S3 Standard states eleven nines, 99.999999999%, of annual object durability). It is achieved by redundancy across failure domains, plus continuous checks and repair.
Replication
Store n full copies (commonly 3) on different nodes and zones.
- Simple; reads served from any copy; fast repair by copying one replica.
- Storage overhead is
ntimes the data (3x for three copies).
Erasure coding
Erasure coding splits data into k data fragments and computes m parity fragments from them (Reed-Solomon codes are the common family). Any k of the k + m fragments can reconstruct the data, so the system tolerates the loss of any m fragments.
- Smallest example:
k = 2,m = 1. FragmentsAandBhold the two halves of the data, and the parity fragment isP = A XOR B. IfAis lost,A = B XOR P. IfBis lost,B = A XOR P. Any 2 of the 3 fragments reconstruct the data, at 1.5x overhead. Reed-Solomon generalizes this to arbitrarym. - Storage overhead is
(k + m) / k. Fork = 6, m = 3: 9 fragments for 6 units of data, 1.5x overhead, tolerating 3 lost fragments. Three-way replication tolerates 2 lost copies at 3x. - Reading a healthy object needs
kfragments fromknodes. Rebuilding a lost fragment needs readingkothers, so repair moves more data than replica copying. - Encoding and decoding consume CPU, and small objects are inefficient to encode.
| Property | 3x replication | Erasure coding (k=6, m=3) |
|---|---|---|
| Storage overhead | 3.0x | 1.5x |
| Failures tolerated | 2 copies | any 3 fragments |
| Repair traffic | read 1 copy | read 6 fragments |
| Read latency | one node | parallel across k nodes |
| CPU cost | none | encode and decode |
| Fit | hot, small data | large, cold or warm data |
Many systems use replication for recently written or hot data and convert to erasure coding as the data cools.
Integrity
Each chunk stores a checksum. Reads verify it, and background scrubbing rereads data to detect silent corruption (bit rot). Detected corruption triggers repair from other copies or fragments. When a node or disk fails, a repair process recreates the lost redundancy on other nodes.
Consistency
S3 provides strong read-after-write consistency for object PUT and DELETE and for LIST, since December 2020. Earlier it offered eventual consistency for overwrites and deletes. A design without a strongly consistent metadata service, where readers may see stale metadata, must offer weaker guarantees, so the metadata store is the component that decides the consistency model.
Multipart upload
Uploading one very large object in a single request is fragile: a network error near the end forces starting over, and a single connection limits throughput. Multipart upload splits the upload into parts:
- Initiate. The client requests an upload and receives an upload ID.
- Upload parts. The client uploads numbered parts, each independently and in parallel, and retries only failed parts. The server returns an ETag (checksum) per part.
- Complete. The client sends the list of part numbers and ETags. The server assembles them into one object and commits the metadata atomically.
- Abort. Uploaded parts of an unfinished upload consume storage until aborted, so lifecycle rules should remove stale incomplete uploads.
sequenceDiagram
participant C as Client
participant S as Object store
C->>S: initiate multipart upload
S-->>C: upload ID
C->>S: upload part 1
C->>S: upload part 2
C->>S: upload part 3
Note over C,S: parts can be sent in parallel and in any order
S-->>C: ETag per part
C->>S: complete (part numbers and ETags)
S-->>C: object createdIn S3, each part except the last must be at least 5 MiB, a multipart upload may have up to 10,000 parts, and a single object may be up to 5 TiB.
Clients uploading from browsers or mobile apps use pre-signed URLs for each part, so file bytes bypass application servers. See design Google Drive and design YouTube for applications of this.
Storage classes and lifecycle
Object stores offer classes that trade retrieval latency and cost for storage price: frequently accessed, infrequent access, and archival tiers. Lifecycle rules transition objects between classes or expire them by age or prefix. Since delivery to users at scale is usually paired with a content delivery network, the object store acts as the origin.
When to use and not use
Use for large immutable blobs, media, backups, logs, static website assets, and data lake files.
Avoid for:
- Frequently updated small records or transactional data.
- Workloads needing POSIX semantics such as atomic rename, file locks, or append.
- Low-latency random access to small ranges.
Interview questions
- Why store objects and metadata separately? Metadata is small, needs ordered, transactional access for lookups and listings, and is updated often. Data is large and immutable and needs cheap, scalable bulk storage. Separating them lets each scale with its own technology.
- Why is erasure coding cheaper than replication and what does it cost? It gives comparable failure tolerance at 1.2x to 1.5x storage instead of 3x, at the cost of CPU for encoding and more network traffic during repair and degraded reads.
- How does multipart upload help with reliability? Parts upload independently and in parallel, only failed parts are retried, and the object becomes visible only when the complete request commits it.
- How does a
LISTwith prefix work on a flat namespace? The metadata store keeps keys in sorted order, so a prefix maps to a contiguous key range that is scanned. A delimiter groups keys sharing a prefix into a single common-prefix entry.
