Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

System Design (High-Level Design)  Module 15 – Files, objects and media

Block, file and object storage

Compare block, file and object storage, see how object stores treat keys, whole-object writes and metadata, and pick storage classes by how often data is read.

  • Beginner
  • 20 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0 and quickjs 0.32.0
  • By MySmartCoPilot
Free: 20 minutes

What you will learn

  • Compare block, file and object storage by interface, sharing and scale
  • Explain how object stores treat keys, whole-object writes, metadata and concurrent writers
  • Choose a storage class from how often data is read and how large each object is

Before you start

What you’ll learn · Before you start

What you will learn

  • Compare block, file and object storage by interface, sharing and scale
  • Explain how object stores treat keys, whole-object writes, metadata and concurrent writers
  • Choose a storage class from how often data is read and how large each object is

Before you start

On this page

Block storage gives one server a raw disk made of numbered blocks. File storage gives many servers a shared tree of directories and files that they can open and change in place. Object storage gives any client, over HTTPS, a flat namespace of keys, each holding a whole object with its metadata. The three often sit on the same kind of drives; what differs is the interface, and the interface decides who can share the data, how a change is written and how far the system can grow. A database wants block storage, software written for a file system wants file storage, and uploads, media, backups and logs at large scale want object storage. This lesson compares the three, shows how an object store behaves when you write, list and overwrite, and prices the storage classes that make old data cheap.

Three interfaces to the same disks

Block storage presents a volume: a long array of fixed-size blocks that the server reads and writes by number. The volume knows nothing about files. The server’s operating system puts a file system on it, or a database writes its pages to it directly, and that software decides what the blocks mean. Because only one owner can safely manage the blocks, a volume is usually attached to one server at a time. A cloud volume such as Amazon EBS behaves like a local hard drive once attached, and its data is copied across several servers inside one Availability Zone (Amazon EBS).

File storage moves the file system onto a server of its own and shares it over the network with a protocol such as NFS or SMB. Many machines mount the same tree at once. Each can open a file, seek to any offset, overwrite a few bytes, append, rename a directory and take a lock, with the semantics that ordinary programs expect. Amazon EFS, for example, speaks NFS version 4 and offers strong data consistency and file locking to many instances at once (Amazon EFS).

Object storage drops the hierarchy and the in-place edits. A bucket maps a key, a string such as users/42/avatar.png, to an object: the bytes plus metadata such as the content type. Clients send HTTP requests to store, read, delete and list objects by key, from anywhere, and the store spreads them over as many machines as it needs. That simple interface is what lets one bucket hold billions of objects for millions of clients.

Block storage: one server, numbered blocks. File storage: many servers, a shared file tree. Object storage: any client, objects by key.Block storageFile storageObject storageOne server: a databaseor a file systemA volume of numberedfixed-size blocksMany servers at onceA shared tree of directoriesand files, edited in placeAny client, anywhereA bucket: key → whole objectplus its metadataread or write block nopen, seek, write, lock(NFS or SMB)PUT, GET, DELETE, LISTover HTTPS

Three interfaces to the same disks

Text description of the diagram

The diagram has three panels, one under the other.

  1. Block storage: one server, running a database or a file system, reads or writes block n of a volume made of numbered fixed-size blocks.
  2. File storage: many servers at once open, seek, write and lock files in a shared tree of directories and files that they edit in place, over a network file protocol such as NFS or SMB.
  3. Object storage: any client, anywhere, sends PUT, GET, DELETE and LIST requests over HTTPS to a bucket that maps each key to a whole object plus its metadata.

The three side by side

Block, file and object storage
Criterion BlockFileObject
Address Block numberFile pathObject key
Smallest change One blockAny bytesWhole object
Shared by One serverMany serversAny client
Interface Disk reads, writesNFS or SMBHTTP by key
Grows to One volumePetabytesNo real limit
Request latency LowestLow, plus networkHighest
When to choose Databases, boot disksShared files, older appsUploads, media, backups, logs

Object storage pays for its reach with latency: every request is an HTTP round trip to a distributed service, and only special low-latency classes such as S3 Express One Zone promise single-digit milliseconds (Amazon S3). Durability differs too, and it surprises people. The Amazon EBS documentation states 99.8 % to 99.9 % durability a year for most volume types, with an annual failure rate of 0.1 % to 0.2 %, while the standard S3 storage classes are designed for 99.999999999 % (EBS, S3 storage classes). A volume is a place to work; the copy you cannot lose belongs in object storage, which is why volume snapshots and database backups are kept there.

How an object store behaves

Four rules explain most of the surprises engineers meet with object storage. The example below follows them in a small model of a bucket and counts the requests and bytes each step costs.

A bucket's rules, step by step Python · object_semantics.py
# A small model of how an object store behaves: a bucket maps a key to a whole object and its metadata. It follows
# the rules object stores document (whole-object writes, flat keys, last writer wins, conditional create) and counts
# the requests and bytes each operation costs. It is a teaching model, not a client for a real service.
import hashlib


class Bucket:
    def __init__(self):
        self.objects = {}  # key -> (bytes, metadata)
        self.requests = 0
        self.bytes_sent = 0

    def put(self, key, data, content_type="application/octet-stream", if_none_match=False):
        self.requests += 1
        self.bytes_sent += len(data)
        if if_none_match and key in self.objects:
            return 412  # Precondition Failed: the key exists, so nothing is overwritten
        etag = hashlib.sha256(data).hexdigest()[:8]  # here a short hash of the bytes
        self.objects[key] = (data, {"Content-Type": content_type, "ETag": etag, "Content-Length": len(data)})
        return 200

    def get(self, key, first=None, last=None):
        self.requests += 1
        data, _ = self.objects[key]
        return data if first is None else data[first : last + 1]  # a Range request reads part of an object

    def head(self, key):
        self.requests += 1
        return self.objects[key][1]

    def delete(self, key):
        self.requests += 1
        self.objects.pop(key, None)

    def copy(self, src, dst):
        self.requests += 1
        self.objects[dst] = self.objects[src]

    def list(self, prefix="", delimiter=None):
        """Keys under a prefix; with a delimiter, the next level is grouped into common prefixes ("folders")."""
        self.requests += 1
        keys = sorted(k for k in self.objects if k.startswith(prefix))
        if delimiter is None:
            return keys, []
        files, folders = [], set()
        for k in keys:
            rest = k[len(prefix) :]
            if delimiter in rest:
                folders.add(prefix + rest.split(delimiter)[0] + delimiter)
            else:
                files.append(k)
        return files, sorted(folders)


b = Bucket()
b.put("users/42/photos/goa/beach.jpg", b"J" * 5_000_000, "image/jpeg")
b.put("users/42/photos/pune/fort.jpg", b"J" * 3_000_000, "image/jpeg")
b.put("users/42/avatar.png", b"P" * 40_000, "image/png")

print("1. Keys are flat names; a delimiter only groups them into prefixes.")
files, folders = b.list("users/42/", delimiter="/")
print("   files:", files)
print("   common prefixes:", folders)
print("   one level down:", b.list("users/42/photos/", delimiter="/")[1])

print("\n2. Changing 10 bytes means writing the whole object again.")
before = b.bytes_sent
data = bytearray(b.get("users/42/photos/goa/beach.jpg"))
data[100:110] = b"0123456789"
b.put("users/42/photos/goa/beach.jpg", bytes(data), "image/jpeg")
print(f"   bytes uploaded for a 10-byte change: {b.bytes_sent - before:,}")
print(f"   but a Range read of 10 bytes returns: {b.get('users/42/photos/goa/beach.jpg', 100, 109)!r}")

print("\n3. Renaming a 'folder' of 1,000 objects is 1,000 copies and 1,000 deletes.")
for i in range(1000):
    b.put(f"tmp/upload-7/part-{i:04d}", b"x")
start = b.requests
keys, _ = b.list("tmp/upload-7/")
for k in keys:
    b.copy(k, k.replace("tmp/upload-7/", "done/upload-7/"))
    b.delete(k)
print(f"   requests: {b.requests - start:,} (1 list, 1,000 copies, 1,000 deletes); a file system renames a directory in one call")

print("\n4. Two clients write the same key: the last write wins and the first is lost silently.")
b.put("users/42/profile.json", b'{"name": "Asha"}', "application/json")
b.put("users/42/profile.json", b'{"name": "Ravi"}', "application/json")
print("   stored:", b.get("users/42/profile.json").decode())
status = b.put("users/42/profile.json", b'{"name": "Meera"}', "application/json", if_none_match=True)
print(f"   a conditional create on the same key gets HTTP {status}, and the stored value stays:", b.get("users/42/profile.json").decode())

print("\n5. Metadata travels with the object and is read without the body.")
print("  ", b.head("users/42/avatar.png"))

Output

1. Keys are flat names; a delimiter only groups them into prefixes.
   files: ['users/42/avatar.png']
   common prefixes: ['users/42/photos/']
   one level down: ['users/42/photos/goa/', 'users/42/photos/pune/']

2. Changing 10 bytes means writing the whole object again.
   bytes uploaded for a 10-byte change: 5,000,000
   but a Range read of 10 bytes returns: b'0123456789'

3. Renaming a 'folder' of 1,000 objects is 1,000 copies and 1,000 deletes.
   requests: 2,001 (1 list, 1,000 copies, 1,000 deletes); a file system renames a directory in one call

4. Two clients write the same key: the last write wins and the first is lost silently.
   stored: {"name": "Ravi"}
   a conditional create on the same key gets HTTP 412, and the stored value stays: {"name": "Ravi"}

5. Metadata travels with the object and is read without the body.
   {'Content-Type': 'image/png', 'ETag': 'a24cdd48', 'Content-Length': 40000}

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 object_semantics.py

Keys are names, not paths. There are no directories. A listing with a prefix and a delimiter groups keys into “common prefixes”, which consoles draw as folders, but nothing is stored for them. So renaming a “folder” means copying and deleting every object under it: 2,001 requests for 1,000 objects in step 3, where a file system renames a directory in one call. Choose keys you will never need to rename, such as a user id and an upload id, and keep human names in metadata or in a database.

Objects are written whole. You cannot change bytes inside an object, and in most buckets you cannot append to it either; S3’s single-zone, low-latency class is an exception that accepts appends to an object, up to 10,000 of them (appending data). Step 2 changes 10 bytes and has to upload all 5,000,000 again. Reads are more flexible: a Range request returns just the bytes asked for, which is how video players and large-file downloaders read pieces. Design data that changes around this rule: split it into chunks and keep a small manifest object that lists them, or write new immutable objects instead of editing old ones. Log segments, database snapshots and media segments all fit naturally.

Reads see the latest write, but concurrent writes race. S3 gives strong read-after-write consistency for PUT and DELETE in all regions: once a write is acknowledged, every following read and listing reflects it (Amazon S3). Older material that calls S3 eventually consistent is out of date for objects; bucket settings such as enabling versioning still take time to spread. Two writers to the same key are another matter: the store keeps the write with the latest timestamp and the other is lost without an error, as in step 4. There is no lock and no transaction across keys. HTTP’s conditional requests close the gap (RFC 9110): in S3, a write with If-None-Match: * fails with 412 Precondition Failed when the key already exists, and If-Match with an ETag writes only if nobody changed the object since you read it (conditional writes).

Metadata travels with the object. Every object carries system metadata (its size, an ETag that changes when the content changes, Content-Type) and any user metadata set when it was written. A HEAD request returns it without the body, as step 5 shows. Metadata cannot be searched, though, so anything you need to query, such as “all photos of user 42 taken in Pune”, belongs in a database row that points at the key.

MIME Type Lookup Look up the Content-Type an object should be stored with, so browsers display it correctly.

One photo upload, three ways

Picture a photo-sharing service whose web servers receive uploads.

  • On a block volume attached to one web server, every photo lives on that server. A second server cannot see them, so the fleet cannot grow without sharding users by server. When the server dies, its photos are unreachable until the volume is attached elsewhere, and when the volume fails, they are gone unless a snapshot exists.
  • On a shared file system, all web servers mount the same tree, so any of them can serve any photo. The file server becomes the shared bottleneck for every read, and its locking and metadata operations slow down as directories fill with millions of files.
  • In an object store, the web servers keep no files at all. They store each photo under a key such as photos/42/9f3c.jpg, record the key in the database, and serve reads through a CDN. Servers can be added or replaced freely. Later lessons in this module let the phone upload straight to the store, skipping the servers entirely.

The third design is the default for user content because it removes state from the servers. The first two remain right for what they are good at: the database behind the service still runs on block storage.

Storage classes: paying less for data nobody reads

An object store charges for bytes stored each month, for requests and, in the colder classes, for every GB read back. Storage classes trade those prices against each other. In S3, Standard has no retrieval fee and no minimums; Standard-IA stores for less but bills a retrieval fee, a minimum storage duration of 30 days and a minimum billable size of 128 KB; Glacier Instant Retrieval is cheaper still, with a 90-day minimum and millisecond reads; Glacier Flexible Retrieval and Deep Archive must be restored before reading (S3 storage classes). A standard restore from Flexible Retrieval typically takes 3 to 5 hours and from Deep Archive up to 12, with bulk restores slower and expedited ones faster for Flexible Retrieval only (retrieval options).

Lifecycle rules move objects between classes by age, so new uploads start in the hot class and cool down automatically. The example prices a photo service of 101 TB under four mixes. The prices are assumptions for the example; real ones depend on the provider and region, so plug in the current list.

One month of storage under four class mixes Python · lifecycle_cost.py
# Monthly storage bill of a photo service under four storage-class mixes. Every number below is an assumption for
# the example: prices differ by provider and region and change over time, so plug in the current price list.
GB = 10**9

# Assumed prices in US dollars: storage per GB-month, retrieval per GB read, and the smallest size an object is
# billed at (small objects in the infrequent-access classes are billed as if they were 128 KB).
CLASSES = {
    "standard": {"store": 0.023, "read": 0.0, "min_bytes": 0},
    "infrequent": {"store": 0.0125, "read": 0.01, "min_bytes": 128_000},
    "archive-instant": {"store": 0.004, "read": 0.03, "min_bytes": 128_000},
}

# The data: 50 million originals of 2 MB and one 20 KB thumbnail each, split by age. "reads" is the share of each
# group's bytes read in a month (originals are opened rarely once they are old; thumbnails are shown all the time).
GROUPS = [
    # name, objects, bytes each, share of the bytes read in a month
    ("originals under 30 days", 5_000_000, 2_000_000, 0.50),
    ("originals 30-180 days", 10_000_000, 2_000_000, 0.05),
    ("originals over 180 days", 35_000_000, 2_000_000, 0.01),
    ("thumbnails under 30 days", 5_000_000, 20_000, 3.0),
    ("thumbnails over 30 days", 45_000_000, 20_000, 3.0),
]

MIXES = {
    "A: everything in standard": ["standard"] * 5,
    "B: originals to infrequent after 30 days": ["standard", "infrequent", "infrequent", "standard", "standard"],
    "C: B, then archive-instant after 180 days": ["standard", "infrequent", "archive-instant", "standard", "standard"],
    "D: C, and old thumbnails forced to infrequent": ["standard", "infrequent", "archive-instant", "standard", "infrequent"],
}


def monthly_cost(cls, objects, size, read_share):
    c = CLASSES[cls]
    billed_gb = objects * max(size, c["min_bytes"]) / GB
    read_gb = objects * size * read_share / GB
    return billed_gb * c["store"], read_gb * c["read"]


stored_tb = sum(n * size for _, n, size, _ in GROUPS) / 10**12
print(f"Data stored: {stored_tb:.0f} TB in {sum(n for _, n, _, _ in GROUPS):,} objects\n")
print("US dollars a month")
print(f"{'mix':<46}{'storage':>8}{'reads':>8}{'total':>8}")
base = None
for name, plan in MIXES.items():
    store = read = 0.0
    for cls, (_, n, size, share) in zip(plan, GROUPS):
        s, r = monthly_cost(cls, n, size, share)
        store += s
        read += r
    total = store + read
    base = base or total
    print(f"{name:<46}{store:>8,.0f}{read:>8,.0f}{total:>8,.0f}  ({total / base:.0%} of A)")

print("\nWhy D costs more than C: each 20 KB thumbnail is billed as 128 KB, and every view pays a retrieval fee.")
s_std, _ = monthly_cost("standard", 45_000_000, 20_000, 3.0)
s_ia, r_ia = monthly_cost("infrequent", 45_000_000, 20_000, 3.0)
print(f"old thumbnails in standard: {s_std:,.0f} a month; in infrequent: {s_ia:,.0f} storage + {r_ia:,.0f} reads")

Output

Data stored: 101 TB in 100,000,000 objects

US dollars a month
mix                                            storage   reads   total
A: everything in standard                        2,323       0   2,323  (100% of A)
B: originals to infrequent after 30 days         1,378      17   1,395  (60% of A)
C: B, then archive-instant after 180 days          783      31     814  (35% of A)
D: C, and old thumbnails forced to infrequent      834      58     892  (38% of A)

Why D costs more than C: each 20 KB thumbnail is billed as 128 KB, and every view pays a retrieval fee.
old thumbnails in standard: 21 a month; in infrequent: 72 storage + 27 reads

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 lifecycle_cost.py

Moving old originals to the infrequent class cuts the bill to 60 %, and moving the oldest to the archive class with millisecond reads brings it to 35 %, because those photos are rarely opened. Mix D shows the trap. The thumbnails are 20 KB but billed as 128 KB in the colder classes, and they are viewed all the time, so each view also pays a retrieval fee: the old thumbnails cost about five times as much there as in standard storage. For the same reason S3 lifecycle rules do not transition objects smaller than 128 KB by default, and each transition is a billed request (S3 Lifecycle).

Three questions pick a class for any dataset. How often is it read? Data read more than about once a month stays standard. How large are its objects? Small objects belong in the classes without a minimum size, or packed together into larger ones. How fast must a rare read be? A legal archive that must answer within seconds needs a class with millisecond access, while a disaster-recovery copy can wait hours for a restore.

Where the bucket is matters too

The class sets the price; the region can be a legal requirement. The Reserve Bank of India requires payment system providers to store the entire data relating to the payment systems they operate in a system only in India (RBI/2017-18/153). For a payments product that means buckets in Indian regions, and checking where replication, backups and log exports send their copies.

Data Storage Converter Convert TB, TiB and GB while you check a storage bill or a class mix.

Interview questions

What is the difference between block, file and object storage? Block storage is a volume of numbered blocks that one server formats and manages, which suits databases. File storage is a shared directory tree that many servers mount and edit in place over NFS or SMB. Object storage is a flat namespace of keys holding whole objects with metadata, read and written over HTTP by any client, which scales furthest and suits uploads, media, backups and logs. The deciding question is which interface the software needs.

Why do object stores replace objects whole, and what do designs do instead? Replacing an object whole keeps every write atomic and lets the store copy and cache objects freely, because an object never changes under a reader. Data that grows or changes is written as new immutable objects: chunks plus a manifest that lists them, numbered log segments, or a new version under a new key with the database pointing at the current one.

Key takeaways

  • Block storage is a disk for one server, file storage a shared tree for many, object storage a key-to-object service for any client; the interface decides sharing, change granularity and scale.
  • Objects are written whole, keys are flat names, and concurrent writers race with the last write winning, so use immutable keys, manifests and conditional writes.
  • S3 reads see acknowledged writes immediately; metadata rides with the object, but anything you query belongs in a database.
  • Storage classes trade storage price for retrieval fees, minimum durations and minimum sizes: cold, large objects save the most, small hot objects can cost more.

Exercise

Exercise · Easy · Python

Price storage classes with their minimum billable size

Write three helpers in class_cost.py that price a group of objects in a storage class. A class is a dictionary such as {"store": 0.0125, "read": 0.01, "min_bytes": 128_000}: the price of one GB stored for a month, the price of one GB read, and the smallest size an object is billed at. A GB here is 10**9 bytes.

billed_gb(objects, avg_bytes, min_bytes) returns the GB you are billed for: every object counts as at least min_bytes. For 1,000 objects of 20,000 bytes with a 128,000-byte minimum that is 0.128, not 0.02.

monthly_cost(objects, avg_bytes, read_share, cls) returns one month's cost: the billed GB times the storage price, plus the GB read times the read price. read_share is the share of the group's real bytes read in the month (0.05 means 5 %, 3.0 means every byte is read three times). Reads are charged on the real bytes, not the billed ones.

cheapest(objects, avg_bytes, read_share, classes) takes a dictionary of class name to class and returns the name of the class with the lowest monthly cost. If two cost the same, return the one that comes first in classes.

Starter code · class_cost.py

def billed_gb(objects, avg_bytes, min_bytes):
    """GB billed for `objects` objects of `avg_bytes` each, each billed as at least `min_bytes`."""
    # Replace this line with your code.
    return 0


def monthly_cost(objects, avg_bytes, read_share, cls):
    """One month's storage cost plus the cost of reading `read_share` of the real bytes."""
    # Replace this line with your code.
    return 0


def cheapest(objects, avg_bytes, read_share, classes):
    """The name of the cheapest class for this group (the first one on a tie)."""
    # Replace this line with your code.
    return ""
The sample tests · test_class_cost.py
import math

from class_cost import billed_gb, cheapest, monthly_cost

STANDARD = {"store": 0.023, "read": 0.0, "min_bytes": 0}
INFREQUENT = {"store": 0.0125, "read": 0.01, "min_bytes": 128_000}
ARCHIVE = {"store": 0.004, "read": 0.03, "min_bytes": 128_000}
CLASSES = {"standard": STANDARD, "infrequent": INFREQUENT, "archive-instant": ARCHIVE}


def test_billed_gb():
    """bills small objects at the minimum size and large ones at their own size"""
    assert math.isclose(billed_gb(1_000, 2_000_000, 0), 2.0)
    assert math.isclose(billed_gb(1_000, 20_000, 128_000), 0.128)
    assert math.isclose(billed_gb(1_000, 200_000, 128_000), 0.2)
    assert math.isclose(billed_gb(5, 128_000, 128_000), 0.00064)


def test_monthly_cost_storage_only():
    """charges the billed GB at the storage price"""
    assert math.isclose(monthly_cost(1_000_000, 2_000_000, 0.0, STANDARD), 46.0)
    assert math.isclose(monthly_cost(1_000_000, 20_000, 0.0, INFREQUENT), 1.6)


def test_monthly_cost_with_reads():
    """adds the read price on the real bytes read, not the billed bytes"""
    assert math.isclose(monthly_cost(1_000_000, 2_000_000, 0.1, INFREQUENT), 27.0)
    assert math.isclose(monthly_cost(1_000_000, 20_000, 3.0, INFREQUENT), 2.2)
    assert math.isclose(monthly_cost(2_000_000, 1_000_000, 0.5, ARCHIVE), 38.0)


def test_cheapest():
    """picks the class that costs least for the access pattern"""
    assert cheapest(1_000_000, 2_000_000, 0.05, CLASSES) == "archive-instant"
    assert cheapest(1_000_000, 2_000_000, 0.5, CLASSES) == "infrequent"
    assert cheapest(1_000_000, 20_000, 3.0, CLASSES) == "standard"
    assert cheapest(1_000_000, 2_000_000, 2.0, CLASSES) == "standard"


def test_cheapest_tie():
    """keeps the first class when two cost the same"""
    same = {"a": {"store": 0.01, "read": 0.0, "min_bytes": 0}, "b": {"store": 0.01, "read": 0.0, "min_bytes": 0}}
    assert cheapest(10, 10**9, 0.0, same) == "a"
A hint

billed_gb is one line with max(avg_bytes, min_bytes). In monthly_cost, compute the GB read from objects * avg_bytes * read_share / 10**9 and add its cost to the storage cost. For cheapest, loop over classes.items() and keep the first name whose cost is lower than the best so far.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Check yourself

6 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 6 A PostgreSQL server writes 8 KB pages at random offsets and needs its own file system on the disk. Which storage fits?

    Choose one answer.

    Show the answer to question 1

    Answer: Block storage, a volume attached to the database server

    The database manages its own on-disk layout and rewrites small pages in place, which is what a block volume offers. An object store would rewrite a whole object for every page change, and a shared file system adds a network round trip and locking the database does not need.

  2. Question 2 of 6 You must change 10 bytes in the middle of a 5 MB object. What does an object store make you do?

    Choose one answer.

    Show the answer to question 2

    Answer: Upload the whole object again under the same key

    Objects are replaced whole. Reads can use a Range header to fetch part of an object, but writes cannot, which is why designs that change data often split it into chunks or write new immutable objects.

  3. Question 3 of 6 Two clients PUT different profile documents to the same key at about the same time, without any condition. What happens?

    Choose one answer.

    Show the answer to question 3

    Answer: The write with the later timestamp is kept and the other is lost without an error

    Without a lock or a condition the last writer wins, and the losing client gets a success response. A conditional write (If-None-Match or If-Match) turns the silent loss into a 412 response the client can handle.

  4. Question 4 of 6 One million thumbnails of 20 KB each move to a class that bills every object as at least 128 KB. How many GB are billed (1 GB = 10^9 bytes)?

    Type a number.

    Show the answer to question 4

    Answer: 128 GB (anything from 127 to 129 counts)

    Each object is billed as 128,000 bytes, so 1,000,000 × 128,000 = 128 × 10^9 bytes, 128 GB, against 20 GB of real data. That is why small, frequently read objects stay in the standard class.

  5. Question 6 of 6 Which of these belong in object storage?

    Choose every answer that is right.

    Show the answer to question 6

    Answer:

    • Nightly database backups
    • Videos that users upload
    • Application logs kept for later analysis

    Uploads, backups and logs are written once, read whole or in ranges, and grow without limit, which suits object storage. A running database rewrites small pages in place and needs a block volume.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.