Markdown Editor

Object Storage System Design Template (S3-Like, Erasure Coding)

S3-like blob store design: consistent metadata, packed volumes, replicas then RS(9,6) erasure coding across AZs, durability maths, repair, deletes

सिस्टम डिज़ाइनपूर्णHaystack (OSDI 2010); f4 (OSDI 2014); docs/48 design standarddesignobjectstoragemath
एडिटर में खोलें.md डाउनलोड करें

उपयोग कैसे करें: Use it when designing or reviewing an object or blob store, or preparing the object storage design interview. Fill the object size distribution and the durability target first, then choose the code and placement so one AZ never holds more fragments than the code can lose. The main pitfall is trusting independent-failure durability numbers while ignoring correlated failures and operator deletes.

प्रीव्यू

System Design: [Object storage service name]

Reference design for an S3-compatible object (blob) store: a strongly consistent metadata service, data placement across failure domains, packing of small objects into large volumes, replication for new data and erasure coding for data that has cooled, durability arithmetic, repair and deletion. It draws on the published Haystack (OSDI 2010) and f4 (OSDI 2014) papers and on the public Amazon S3 documentation for API behaviour. It follows the structure of the System Design Document template, adds a 45-minute interview path, access-pattern and failure-mode tables and a cited "How real systems do it" box, and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks.

Document control

FieldValue
Document ID[SDD-OBJ-001]
System / feature[Object storage service]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
DifficultyAdvanced
API compatibility target[S3 REST API subset, listed in 4.1]
Related[Backup policy], [Data retention schedule], [ADR: erasure code parameters]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
SRE / operations[@name][Decision]YYYY-MM-DD
Security[@name][Decision]YYYY-MM-DD
Hardware and capacity planning[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Changed erasure code from RS(10,4) in one zone to RS(9,6) across three zones
0.3YYYY-MM-DD[@name]Example: Added crypto-shredding for deletes in erasure-coded volumes
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Product teams store user uploads, backups and analytics files on a network file system that holds 3 copies of everything. It costs three times the logical bytes, listing a directory with millions of files takes minutes, and two disk-shelf failures in one rack last year made 4 TB unavailable for a day. The company needs an internal object store with an S3-compatible API, lower storage overhead and a stated durability target.]

1.2 Proposed solution

[Example: A regional service across three availability zones (AZs). Stateless front ends speak the S3 REST API. A metadata service, sharded by bucket and key range on consensus-replicated groups, maps each object version to its data location and gives strong read-after-write consistency. New objects are written as three replicas, one per AZ, into large append-only volumes; small objects are packed many to a volume so a read costs one disk seek. After 30 days without change, volumes are converted to a Reed-Solomon RS(9,6) code with five fragments per AZ, which survives the loss of a whole AZ plus one more disk at 1.67 times the logical size. Background scrubbers verify checksums and a repair service rebuilds lost fragments.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: Replication or erasure coding?Both: 3 replicas while hot, RS(9,6) across 3 AZs after 30 days7.3, 10
Q-02Example: Consistency for GET and LIST after PUT?Strong read-after-write for object operations; bucket configuration eventually consistent7.1
Q-03Example: How are small objects stored?Packed into 100 GB append-only volumes with an in-memory index7.2
Q-04Example: How do deletes reclaim space in coded volumes?Per-object key deleted at once (crypto-shredding); space reclaimed by periodic rewrite7.6
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

Use this order when the document serves an interview or a short design review. The written sections below are the long form of each step.

MinutesCoverOutput on the whiteboard
0 to 5Scope: PUT, GET, DELETE, LIST, multipart; consistency; durability target; below-the-line items (2.3)Five operations and two numbers
5 to 10Estimates: objects, bytes, request rates, raw capacity under replication and erasure coding (section 3)"Metadata is 100 TB, data is 87 PB raw"
10 to 15Interface: PUT and GET with conditional headers, multipart upload (section 4)Three calls
15 to 25High-level design: front end, metadata service, storage nodes, placement, repair (section 6)One diagram
25 to 40One deep dive: durability and erasure coding (default, 7.3), or metadata and LIST (7.1), or small-object packing (7.2), or deletes (7.6)Options, choice, reason
40 to 45Failures (disk, AZ, metadata shard, silent corruption), the 10x row in section 10Two failure rows

Start the default deep dive with the naive answer, three full copies, and work out its cost (150 PB raw for 50 PB of data). Then introduce a Reed-Solomon code, show why the fragments must be spread so one AZ holds no more fragments than the code can lose, and only then compute durability.

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: PUT, GET (with byte ranges), HEAD, DELETE objects in bucketsMust
FR-02Example: Multipart upload for large objects, with parts uploaded in parallel and resumedMust
FR-03Example: LIST objects by prefix with pagination, in lexicographic key orderMust
FR-04Example: Conditional writes (If-None-Match: * to create only, If-Match on ETag)Must
FR-05Example: Object versioning per bucket and retention locks (write once, read many)Must
FR-06Example: Lifecycle rules: expire objects and versions after a set ageShould
FR-07Example: Asynchronous replication of a bucket to another regionShould
FR-08Example: Event notifications on create and deleteCould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01DurabilityExample: Design target of at least 11 nines per object per year, under the model in 7.3Model plus scrubber and repair metrics
NFR-02AvailabilityExample: 99.99% of GET and PUT requests succeed per month; survives loss of one AZFront end success ratio, AZ evacuation drill
NFR-03ConsistencyExample: A GET or LIST started after a successful PUT or DELETE sees its effectLinearizability tests on the metadata service
NFR-04LatencyExample: First byte p99 at or below 100 ms for objects under 1 MiBFront end timing
NFR-05CostExample: Raw-to-logical ratio at or below 1.8 averaged over the fleetCapacity reports
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

Name these explicitly so reviewers and interviewers do not pull the design toward them.

  • [Example: a POSIX file system interface or in-place partial updates of objects]
  • [Example: content delivery to end users (a CDN sits in front)]
  • [Example: tabular or vector bucket types and query in place]
  • [Example: cross-region strong consistency (replication is asynchronous)]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
Logical data storedLLExample: 50 PBCurrent file systems x growth
Objects storedNNExample: 200 billionInventory of current files
Mean object sizesˉ=L/N\bar{s} = L / N250 KBDerived; median is far smaller
Peak PUT rateWWExample: 5 000/s (average 2 000/s)Upload logs
Peak GET rateGGExample: 100 000/sAccess logs
Share of bytes in the replicated (hot) tierhhExample: 5%Objects younger than 30 days
Drive size and target fillDD, ffExample: 20 TB, 80%Hardware plan
Metadata per object versionmmExample: 500 bytesKey, version, size, checksum, location, tags
Annual failure rate of a driveAFRExample: 2%Fleet statistics
Time to detect and repair a lost fragmentTTExample: 24 hRepair service target

3.2 Bandwidth

Bput=W×sˉ=5 000×250 KB=1.25 GB/s,Bget=G×sˉ=100 000×250 KB=25 GB/s≈200 Gbit/sB_{put} = W \times \bar{s} = 5\,000 \times 250 \ \text{KB} = 1.25 \ \text{GB/s}, \qquad B_{get} = G \times \bar{s} = 100\,000 \times 250 \ \text{KB} = 25 \ \text{GB/s} \approx 200 \ \text{Gbit/s}

Three replicas on write mean 3.75 GB/s of disk writes at peak, and the later conversion to RS(9,6) writes another 1.25×15/9≈2.081.25 \times 15/9 \approx 2.08 GB/s on average when it catches up with peak intake. At the average PUT rate the gross intake is about 1.3 PB a month before deletes. Consequence: reads, not writes, size the network; the front end tier is sized on 200 Gbit/s egress and a cache absorbs the hottest objects.

3.3 Raw capacity

SchemeOverhead (raw / logical)Raw for 50 PBSurvives
3 replicas, one per AZ3.0150 PBLoss of one AZ plus one more copy
RS(10,4) inside one AZ1.470 PBFour lost fragments, but not the loss of that AZ
RS(6,3) across 3 AZs (3 per AZ)1.575 PBOne AZ, and nothing more while it is down
RS(9,6) across 3 AZs (5 per AZ)1.6783.3 PBOne AZ plus one more fragment
Chosen blend: 5% at 3.0, 95% at RS(9,6)1.7386.7 PBAs above
drives=86.7 PB20 TB×0.8≈5 417,servers=5 41724≈226 (about 75 per AZ)\text{drives} = \frac{86.7 \ \text{PB}}{20 \ \text{TB} \times 0.8} \approx 5\,417, \qquad \text{servers} = \frac{5\,417}{24} \approx 226 \ (\text{about } 75 \text{ per AZ})

Consequence: erasure coding saves about 63 PB of raw disk against three replicas, which pays for the extra CPU and repair traffic many times over.

3.4 Metadata

M=N×m=2×1011×500 B=100 TB,300 TB with three replicasM = N \times m = 2 \times 10^{11} \times 500 \ \text{B} = 100 \ \text{TB}, \quad 300 \ \text{TB with three replicas}

At 2 TB per metadata shard that is 50 shards, each a three-member consensus group. Every GET needs one metadata lookup (100 000/s at peak) unless the front end caches the location of immutable versions. Consequence: metadata does not fit in memory on one machine and must be range-partitioned from day one.

3.5 Disk operations

  • Average GET load per drive: 100 000/5 417≈18100\,000 / 5\,417 \approx 18 reads/s, well below the roughly 100 random reads a second an HDD sustains, but only if a GET costs one seek (7.2).
  • Objects per drive: 2×1011/5 417≈3.7×1072 \times 10^{11} / 5\,417 \approx 3.7 \times 10^{7}. With a 32-byte in-memory index entry per object that is 1.2 GB of index per drive, about 28 GB per 24-drive server. Consequence: the storage-node index fits in memory, so no disk read is spent on finding the object.

3.6 Summary

QuantityEstimateDesign consequence
Egress25 GB/s (200 Gbit/s) peakFront ends sized on bandwidth; hot-object cache
Raw capacity86.7 PB (5 417 drives, about 226 servers)RS(9,6) for cold data, 3 replicas for 30 days
Metadata100 TB per copy50 consensus-replicated range shards
Seeks per GET1Packed volumes and in-memory volume index

4. API design

4.1 Interfaces

OperationRequestNotes
Put objectPUT /{bucket}/{key} with Content-MD5 or a checksum headerSingle request up to Example: 5 GiB; returns ETag and version ID
Get objectGET /{bucket}/{key}?versionId= with optional RangeRange reads touch only the needed fragments
Head objectHEAD /{bucket}/{key}Metadata only
Delete objectDELETE /{bucket}/{key}Adds a delete marker in versioned buckets
List objectsGET /{bucket}?list-type=2&prefix=&delimiter=&continuation-token=Up to 1 000 keys per page, lexicographic order
Multipart uploadPOST ?uploads, PUT ?partNumber=&uploadId=, POST ?uploadId= (complete), DELETE ?uploadId= (abort)Parts uploaded in parallel and retried independently
Conditional createPUT with If-None-Match: *Fails with 412 if the key exists; makes "create once" safe

For reference, the public Amazon S3 documentation (checked October 2026) lists multipart parts of 5 MiB to 5 GiB, at most 10 000 parts and a maximum object size of 48.8 TiB; choose your own limits and publish them, and check the provider page if you need exact compatibility.

4.2 Multipart flow

Parts become visible only when the completion commits the version in one metadata transaction, so readers never see half an object. Incomplete uploads expire by lifecycle rule (Example: 7 days) and their parts are garbage-collected.

4.3 Error example

A conditional create that loses the race gets 412 and must not retry the same create; the client reads the existing version instead.

HTTP/1.1 412 Precondition Failed
Content-Type: application/problem+json

{"type": "https://storage.example.com/problems/precondition-failed", "title": "Object already exists", "status": 412, "detail": "If-None-Match: * was set and the key reports/2026/q3.parquet already has a current version.", "instance": "/analytics/reports/2026/q3.parquet"}

5. Data model

5.1 Entities

A volume is an append-only container (Example: 100 GB). While open it is written as three replicas; once sealed and cold it is encoded as nine data and six parity fragments. Objects point at volumes, not disks, so moving or re-encoding a volume never touches object metadata.

5.2 Storage choices

DataStoreKeyMain queriesWhy
Object versions and extentsExample: Range-partitioned key-value store on consensus groups(bucket, key, inverted version)Point lookup, prefix scan for LISTStrong consistency and ordered scans
Volume and fragment mapSeparate placement service, replicatedvolume_idWhere are the fragments of volume VSmall (millions of volumes), changes on repair
Volume index on storage nodesMemory, rebuilt from an index file on disk(volume_id, object offset)Offset and length of an object in a volumeOne seek per read
Object bytesStorage nodes, raw disks or large filesVolume, offsetSequential append, positioned readNo file-per-object metadata overhead

5.3 Access patterns

Access patternFrequencyKey or index that serves itPartition key rationale
GET latest version of a key100 000/s peakMetadata point lookup on (bucket, key), newest version firstRange partitions keep keys in order; hot ranges split automatically
PUT a new version5 000/s peakInsert (bucket, key, version) after data is durableSame partition as reads of that key, so read-after-write is local to one group
LIST by prefixThousands/sOrdered scan of (bucket, key) from the prefixHash partitioning would scatter a prefix; range partitioning keeps it on one or few shards
Find fragments of a volumeEvery GET miss in cache, every repairPlacement map by volume_idSmall map, cached in front ends
Expire objects by lifecycleDaily batchPer-bucket scan by creation time indexBatch work, never on the request path
Repair a lost diskRare, largePlacement map reverse index disk_id to fragmentsLets repair start in seconds after a failure

Sequential key names (timestamps as prefixes) concentrate writes on the last range. The metadata service splits a range when its write rate stays above a threshold, and documentation tells clients that prefixes spread load.

6. High-level design

ComponentResponsibilityScales by
Front endAuthenticate, sign-check, stream data, compute checksums, call metadataBandwidth and connections
Metadata serviceObject versions, extents, LIST order, conditional writesShards (key ranges)
Placement serviceMap volumes to fragments and disks; choose disks for new volumesVolumes (small)
Storage nodesAppend to open volumes, serve positioned reads, keep volume index in memoryDisks
EncoderConvert sealed cold volumes from 3 replicas to RS(9,6)Background throughput
ScrubberRead every fragment periodically and verify checksumsDisk read budget
Repair serviceRebuild missing or corrupt fragments on other disksRepair bandwidth
Garbage collector and lifecycleExpire versions, delete keys, reclaim volume spaceBatch

7. Detailed design

The deep dives in this section, each with options, choice and reason:

Deep diveOptions consideredChoiceReasonSection
Metadata and consistencyEventually consistent hash-partitioned store, relational database, range-partitioned consensus groupsRange-partitioned consensus groupsStrong read-after-write and ordered LIST7.1
Small objectsFile per object, packed volumesPacked append-only volumesOne seek per read, no per-file metadata7.2
RedundancyReplicas only, erasure code only, replicas then code3 replicas for 30 days, then RS(9,6) across AZsCheap writes and reads while hot, 1.67x when cold7.3
DeletesRewrite volumes on every delete, tombstones and compaction, per-object keysPer-object keys plus periodic rewriteImmediate logical delete in coded volumes7.6

7.1 Metadata service and consistency

  • Keys are ordered by (bucket, key) and split into ranges. Each range is a consensus group of three members in three AZs; a write commits when two members accept it.
  • A PUT writes the data first, then commits the version in metadata. Only the commit makes the object visible, so a crash between the two leaves orphan data for garbage collection, never a visible broken object.
  • Reads of the latest version go to the range leader (or to a follower with a read lease), so a GET after a successful PUT always sees it. LIST scans the same ordered ranges, so it also sees new keys at once.
  • Two concurrent PUTs to the same key both succeed; the later commit becomes the latest version. If-Match and If-None-Match let clients avoid lost updates. There are no transactions across keys.
  • Bucket configuration (policies, lifecycle, versioning state) is cached in front ends and is eventually consistent for a short interval; document it.

7.2 Packing small objects into volumes

A file per object costs inodes, directory lookups and extra seeks. Instead, each storage node appends objects ("needles") to a large volume file and keeps an in-memory map from object ID to offset and length. A GET is then one metadata lookup (often cached) plus one disk read. Each needle carries a header with its ID, size and checksum, so the in-memory index can be rebuilt by scanning the volume, and a periodic index checkpoint keeps restarts fast. Objects larger than Example: 16 MiB skip packing: they are split into 8 MiB extents and erasure-coded directly, because a large object gains nothing from replication-first writes.

7.3 Redundancy and durability

Placement. For RS(9,6) the 15 fragments of a volume go to 15 different servers in 15 different racks, five per AZ. Losing an AZ removes five fragments; nine of the remaining ten are enough to read, so data stays available and one more failure is still tolerated.

Durability model. With independent drive failures, the probability that one drive holding a fragment fails during a repair window of TT hours is

p=AFR×T8 760=0.02×248 760≈5.48×10−5p = \text{AFR} \times \frac{T}{8\,760} = 0.02 \times \frac{24}{8\,760} \approx 5.48 \times 10^{-5}

A stripe of nn fragments that tolerates n−kn-k losses is lost when more than n−kn-k fragments fail within the same window:

Pwindow=∑j=n−k+1n(nj)pj(1−p)n−j,Pyear≈Pwindow×8 760TP_{window} = \sum_{j=n-k+1}^{n} \binom{n}{j} p^{j} (1-p)^{n-j}, \qquad P_{year} \approx P_{window} \times \frac{8\,760}{T}
SchemePwindowP_{window}PyearP_{year} per stripeNines
3 replicas1.6×10−131.6 \times 10^{-13}6.0×10−116.0 \times 10^{-11}10.2
RS(6,3)1.1×10−151.1 \times 10^{-15}4.1×10−134.1 \times 10^{-13}12.4
RS(10,4)9.9×10−199.9 \times 10^{-19}3.6×10−163.6 \times 10^{-16}15.4
RS(9,6)9.5×10−279.5 \times 10^{-27}3.5×10−243.5 \times 10^{-24}23.5

Read this table with care. The model assumes independent failures and a fixed repair window; real losses come from correlated events the model ignores: a power or cooling failure in a rack, a bad firmware batch, a bug in the encoder, an operator deleting the wrong volume. The design therefore spreads fragments across racks and AZs, mixes drive batches, verifies every encoded volume by decoding it before the replicas are dropped, and keeps versioning and retention locks as the defence against logical deletion. The extra margin of RS(9,6) also matters while an AZ is down: with five fragments already gone, a remaining stripe is lost only if two of the other ten fail in a window, about 1.35×10−71.35 \times 10^{-7} per 24-hour window, which is why AZ outages trigger priority repair.

Repair speed. Rebuilding a 20 TB drive (16 TB used) onto one spare at 150 MB/s takes about 29.6 hours; spreading the rebuild across 100 drives at 50 MB/s each takes about 0.9 hours. Distributed repair is what keeps TT small. Rebuilding one RS(9,6) fragment reads nine fragments, so repair traffic is nine times the lost bytes and must be throttled against client traffic.

7.4 Write and read paths

The front end acknowledges only after all three replicas have synced and the metadata commit succeeded. If one replica fails, the front end writes the object to a different open volume rather than accepting two copies. A GET reads one replica (nearest AZ first) or, for coded volumes, the one data fragment that holds the object; it falls back to a decode from any nine fragments when that fragment is missing, and verifies the checksum before returning bytes.

7.5 Scrubbing and silent corruption

Every fragment is read and checksummed at least once every Example: 30 days. A mismatch marks the fragment bad and queues a repair from the other fragments. Front ends verify checksums on every read as well, so a corrupt fragment is never served even before the scrubber finds it.

7.6 Deletion, versioning and space reclamation

  • A DELETE in a versioned bucket adds a delete marker; older versions stay until lifecycle rules expire them. Retention locks block deletion and overwrite until a date, including for administrators in compliance mode.
  • In replicated volumes, deleted needles are marked in the index and the volume is compacted by copying live needles to a new volume.
  • In coded volumes, each object is encrypted with its own data key stored in metadata. Deleting the key makes the bytes unreadable at once (crypto-shredding). Space is reclaimed later by rewriting volumes whose live share has fallen below Example: 60%.

7.7 How real systems do it

How real systems do it (paraphrased, not copied). The Haystack paper (Beaver, Kumar, Li, Sobel and Vajgel, OSDI 2010) describes the photo store of a large social network that, at the time, served over a million images a second at peak. The authors found that a network file system spent disk operations on file metadata, so Haystack packs photos into large volume files (about 100 GB each) and keeps a compact in-memory map from photo to offset, using on average about 10 bytes of memory per photo, so a read needs at most one disk operation. The f4 paper (Muralidhar and co-authors, OSDI 2014) adds a warm tier: once data is older and read less, volumes move from Haystack's replicated layout (effective replication 3.6, three copies on RAID-6) to Reed-Solomon(10,4) inside a cell, with blocks of a stripe on different racks, and an XOR of two volumes in a third region for disaster tolerance, which brings the effective replication factor to 2.1. f4 handles deletes by removing a per-object encryption key. This design keeps the same ideas: packed volumes (7.2), hot then cold redundancy (7.3) and key deletion (7.6). Read the originals in 12.3.

8. Scalability and performance

ConcernApproachLimit before redesign
GET rateOne seek per read, location cache in front ends, hot-object cacheSeek budget of about 100/s per HDD
Metadata rateRange shards split on loadExample: about 20 000 writes/s per shard before a split
Sequential key hot spotAutomatic range split, guidance on prefixesOne key range accepting all new keys
Large objectsDirect erasure coding in 8 MiB extents, parallel partsFront end bandwidth
Repair trafficDistributed rebuild, throttledNine bytes read per byte rebuilt for RS(9,6)
Capacity growthAdd servers per AZ in balanced groups; placement prefers empty disksUneven AZ capacity breaks five-per-AZ placement

Latency budget for a GET of a 200 KB object (target p99 100 ms to first byte):

StepBudget
Authentication and request parsing2 ms
Metadata lookup (cache miss)10 ms
Placement lookup (cached)1 ms
Storage node seek and read40 ms
Checksum and first byte to client5 ms
Headroom42 ms

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
DiskDrive failureI/O errors, missed heartbeatsFragments on that drive; no data unavailableDistributed repair from other fragmentsExample: about 1 h of repair
Server or rackPower or switch failureHeartbeats per rackOne fragment per stripe (one rack per fragment)Placement rule, repair after a grace period of 15 min to avoid needless rebuildsExample: 15 min plus repair
AZWhole AZ lostMultiple rack alarms, provider statusReads decode from 10 of 15 fragments; writes go to two AZsPriority repair; new hot writes use two AZs plus a later third copyExample: reads continue; full redundancy restored in days
Metadata shardLeader lossConsensus heartbeatsKeys in one range for a few secondsLeader election within the groupExample: 5 s
EncoderBug writes bad parityDecode verification before replicas are droppedVolumes encoded since the bugKeep replicas until a full decode check passesExample: none (replicas kept)
FragmentSilent corruptionRead-path checksums, scrubberOne fragmentRepair from other fragmentsExample: minutes
OperatorWrong bucket or volume deletedAudit log, delete-rate alarmData under that bucketVersioning, retention locks, delayed physical deletion (7 days)Example: hours, by undelete
[Component][Failure][Signal][Scope][Mitigation][Time]

9.2 Security

ThreatControl
Public exposure of private bucketsBuckets private by default; account-level block on public access
Stolen credentialsShort-lived signed requests, scoped keys, anomaly alerts on egress
Data at rest on stolen or returned disksPer-object data keys wrapped by a key management service; crypto-shredding on decommission
Ransomware or malicious deletionVersioning, retention locks, separate admin roles, delayed physical deletion
[Threat][Control]

9.3 Observability

SignalMetric or logAlert threshold
Durability riskStripes with fewer than full fragments, by fragments missingAny stripe missing 4 or more
Repair backlogBytes waiting for repair, oldest item ageOldest above 24 h
Scrub coverageShare of fragments verified in 30 daysBelow 100%
Request healthError and latency by operation and AZp99 first byte above 100 ms for 10 min
CapacityFill per AZ and per disk classAbove 80%

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Storage servers[$/server-month]Example: about 226 servers with 24 x 20 TB drives[$]
Metadata servers[$/server-month]Example: 150 (50 shards x 3)[$]
Front ends and caches[$/server-month]Sized on 200 Gbit/s[$]
Network between AZs[$/GB]Replica writes plus repair traffic[$]
Total[$]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
Redundancy3 replicas; RS(10,4) in one AZ; RS(9,6) across AZsReplicas while hot, RS(9,6) when coldAZ tolerance at 1.67x; fast hot readsEncoding work, repair reads nine fragments
Metadata storeEventually consistent hash store; consensus range shardsConsensus range shardsRead-after-write and ordered LISTCross-AZ latency on every write
Small objectsFile per object; packed volumesPacked volumesOne seek per readCompaction and index rebuild logic
Deletes in coded volumesRewrite at once; per-object keysPer-object keysImmediate, cheap logical deleteKey management on the read path
Cross-regionSynchronous; asynchronous per bucketAsynchronous, opt-inNo cross-region latency on PUTRecovery point equals replication lag
What changes at 10x / 0.1x10x (500 PB, 2 trillion objects): about 54 000 drives and 1 PB of metadata per copy, so split into independent cells per region with buckets assigned to cells, and consider a wider code such as RS(12,6) to cut overhead to 1.5. 0.1x (5 PB): three replicas everywhere is simpler and the extra disk is affordable; erasure coding can waitReview at each doubling of logical bytesMetadata shards and repair bandwidth grow first[Note]
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Front end, metadata, replicated volumes, PUT, GET, LISTAPI conformance tests pass; consistency tests passYYYY-MM-DD
M2Multipart, versioning, lifecycleOne pilot team migratedYYYY-MM-DD
M3Encoder, scrubber, distributed repairAZ evacuation drill with no data lossYYYY-MM-DD
M4Retention locks, crypto-shredding, cross-region replicationSecurity review signed offYYYY-MM-DD

11.2 Rollout and rollback

[Example: Teams copy data in with checksums verified on both sides and keep the old file system read-only for 60 days. The encoder starts with verification only (encode, decode, compare, keep replicas) for 30 days before any replica is dropped. Rollback of the encoder means keeping replicas, which costs capacity but no data.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Correlated drive failures from one firmware batchMediumHighMix batches per stripe; firmware updates in waves[@name]
R-02Example: Hot key ranges overload one metadata shardMediumMediumLoad-based splits; prefix guidance[@name]
R-03Example: Repair traffic hurts client latency after an AZ lossMediumMediumRepair throttles by priority; durability-first override[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Do we need a locally repairable code to cut repair reads below nine fragments?[@name]YYYY-MM-DD
OQ-02Example: Which buckets need cross-region replication and in which regions (data residency)?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
VolumeLarge append-only container that holds many objects
NeedleOne object inside a volume, with its own header and checksum
StripeThe k data and n minus k parity fragments computed together
RS(k, m) in this documentReed-Solomon code with k data and m parity fragments, written RS(9,6) for 9 plus 6
Effective replication factorRaw bytes stored divided by logical bytes
ScrubbingReading stored data to detect corruption before a client does
Crypto-shreddingDeleting data by destroying the key that encrypts it
[Term][Meaning]

12.3 References

ReferenceUse
Beaver, Kumar, Li, Sobel, Vajgel, "Finding a needle in Haystack: Facebook's photo storage", OSDI 20107.2, 7.7
Muralidhar and co-authors, "f4: Facebook's Warm BLOB Storage System", OSDI 2014, pages 383 to 3987.3, 7.6, 7.7
Amazon S3 data consistency model, AWS documentation, checked October 2026Behaviour reference for 7.1
Amazon S3 multipart upload limits, AWS documentation, checked October 2026Limits reference for 4.1
RFC 9457 Problem Details for HTTP APIsError body (4.3)
Distributed Key-Value Store System Design (system-design/design-distributed-kv-store)Consensus and partitioning for the metadata service
Photo Sharing System Design (system-design/design-photo-sharing)A main client of this store
CDN System Design (system-design/design-cdn)Delivery in front of the store
Backup Policy (ops/backup-policy)What versioning does not replace
Back-of-Envelope Estimation and Capacity Model (system-design/back-of-envelope-estimation)Method for section 3

Standard and licence note

Based on common industry practice for object storage, the published Haystack (OSDI 2010) and f4 (OSDI 2014) papers and the public Amazon S3 documentation cited in 12.3, used only as a behaviour reference. The papers are paraphrased in 7.7 only; no text, figures or code were copied. The durability figures come from the simple independent-failure model in 7.3 and are illustrative, not a guarantee; all capacity numbers are examples computed from the stated assumptions. Original text written for this collection. Template licence: MIT.

संबंधित टेम्पलेट