Skip to content

The bytes are durable. Why can't the database use this object bucket as its disk?

The Object Exists. Is It Safe? · Part 1 of 6 · 6 min read

Read the worked explanation ↓

Interview question. Your team has moved backups and images into inexpensive object storage. Someone proposes moving the production database's data files there too, arguing that the storage is durable and scalable. Explain the difference between object, block, and file storage, then decide which interface the database actually needs.

A product engineer might see three places that hold bytes and wonder why we have three different categories. The reason is not the material that stores the bytes. It is the agreement between an application and the storage interface about what can be named, changed, shared, and synchronized. Before comparing prices, I would ask what the database does to a single page during a transaction.

A typical database engine doesn't replace a 200 GB data file whenever an 8 KB leaf page changes. It addresses page offsets, manages dirty pages, and expects its filesystem or block device to honor specific write, flush, and failure semantics. Object storage exposes a much coarser unit of mutation. A key names an object. The application normally puts or retrieves a complete object, perhaps fetching a range, but a range GET is not an in-place byte-range write.

Three different interfaces place responsibility for file structure, offsets, metadata and publication at different layers.
Three different interfaces place responsibility for file structure, offsets, metadata and publication at different layers.
Think first

An analytics company wants one storage platform for a PostgreSQL primary, 10 TB nightly exports, and a shared folder of analyst scripts. Choose an interface for each and explain the performance and failure contracts you require.

Take a few minutes to form an approach, then compare it with the worked explanation.

Reveal the worked explanation

Start with the operations, not the brand names

A block device presents logical blocks at addresses. An operating system can build ext4 or XFS on top, and the database can open files on that filesystem. The block service need not know that an address contains a B-tree page, journal record, or directory inode. A cloud volume such as EBS fits this category. Block storage can be network-attached while still exposing disk-like semantics. That doesn't eliminate latency or durability questions, but it gives the OS a suitable primitive.

A file system exposes named files, paths, directories, permissions, reads at offsets, and some form of shared access or locking contract. NFS-backed shared storage such as EFS is useful when several application instances need a common directory tree. Its performance and consistency details matter. A file interface does not promise that every distributed database can safely share one file, because database engines may require exclusive writers, specific locking guarantees, or coordinated journal ownership.

An object service exposes a bucket, an object key, metadata, and operations such as PUT, GET, DELETE, and LIST. It is excellent for immutable images, model artifacts, exports, logs packaged as objects, and backups. Object metadata, lifecycle policy, versioning, and access control can be managed separately from an application's file layout. The tradeoff is that updating a 4 KB section is not the same native operation as a database page write.

A database's IO contract is surprisingly specific

Suppose a database modifies three random pages in a large index and commits one transaction. With a suitable filesystem and underlying block volume, it writes a log record, waits for the required durable acknowledgment, and eventually flushes the dirty pages. The engine controls page addresses and recovery order. In a naive object-backed implementation, each changed page might require fetching and publishing an entire large object. Even if the provider supports efficient ranged reads, those do not supply arbitrary atomic ranged overwrites.

You can build a database over object storage, but that is a different architecture. A cloud-native engine may write immutable segments to objects, maintain a separately coordinated manifest, use local SSD as a cache, and commit through a metadata transaction service. It is not simply taking a conventional database executable and changing a filesystem path to s3://bucket/index.db. The transactional state machine must understand the object API.

This is the first distinction an interviewer should hear. Object storage is not unsuitable for databases in general. Its mutation and publication contract is different from a disk interface. Systems designed around immutable segments or log-structured files can use it effectively, but their metadata, durability, and cache strategies are part of the database design.

Decide using four workload questions

First, what is the mutation granularity? Small random overwrites favor block-oriented storage with a database-managed layout. Whole-object replacement favors objects. Second, what is the namespace? Several tools that need ordinary file paths might benefit from a shared file system, while a service uploading signed, immutable assets benefits from object keys.

Third, who coordinates writers? A shared file path is not a transaction manager. A last-writer-wins object overwrite is not equivalent to a row lock or compare-and-swap on multiple database records. The database needs an authoritative ownership and conflict protocol regardless of where bytes live.

Fourth, what is the failure contract? A successful object PUT can provide strong per-object visibility, while the service still offers no general atomic transaction across multiple object keys. A successful filesystem write() can leave data in volatile cache until a synchronization boundary. Neither interface substitutes for understanding the exact acknowledgment and crash semantics.

For a concrete design, I would place a conventional relational database's data files on a supported filesystem over persistent block volumes, keep object storage for backups, immutable exports, and older large artifacts, and use a shared file service for workflows that genuinely require a shared directory namespace. I'd validate this with a trace of actual IO: random read/write size, sync frequency, metadata operations, object count, read amplification, and the cost of restoration.

In the interview, the strongest answer isn't a memorized table comparing S3, EBS, and EFS. It's the ability to inspect an application's required operations and notice where an apparently cheaper storage interface changes the correctness contract. Sometimes the right solution is to redesign the application around immutable objects. Other times the right decision is simply to keep the database on a disk-like interface rather than pretending the interfaces are interchangeable.

Go deeper

A user-space object-backed filesystem can translate POSIX-looking operations into object calls, but that translation may provide different metadata consistency, locking, append, rename, and durability behavior from a local filesystem. Database engines should use an explicitly supported storage configuration, not assume that a mounted object bucket inherits all local filesystem semantics. Network block volumes also have their own attachment, throughput, failover and synchronization constraints. For object-native databases, separating large immutable data files from small transactional manifests is a common strategy, but the manifest commit requires a correctness proof of its own. The term durable is not synonymous with atomic across keys, low latency, or POSIX-compatible.

Check your reasoning

  • Distinguish block addresses, file paths and object keys by native API.
  • Relate small random page overwrites and WAL to supported block/filesystem semantics.
  • Explain immutable-segment databases built specifically over object storage.
  • Define shareability, file locking, consistency and durable publication.
  • Choose storage per workload and measure request and failure contracts.

Common mistake: Range GET support makes an object bucket a drop-in random-write block device.

Which storage choice best preserves the contracts of a conventional database and large immutable exports?

Read the answer explanation

Use supported block/filesystem storage for a conventional DB and immutable objects for exports — The application mutation and crash contract must match the storage API, regardless of durability marketing.

Apply it elsewhere

A distributed vector-index service stores immutable vector segments in objects and serves queries from local SSD caches. Design a safe manifest publication mechanism when new segments arrive while old queries continue reading.

Compare your approach

Identify block addressing, file namespaces, object-level mutation, log and synchronization needs, write coordination, and the distinction between object-native designs and a conventional database on an object mount.

One more constraint

If a bucket supports byte-range GET requests and strong PUT consistency, can an unmodified database safely treat it as a random-write disk?

Quick revision

Block storage supplies disk-like addressed blocks for a filesystem or database. File storage supplies a directory and file API, often shared across hosts. Object storage supplies key-addressed complete objects and metadata, with range reads but not general in-place random overwrites. A traditional database usually needs supported filesystem and block semantics for page updates and log synchronization. Object-native databases can work well by using immutable segments plus an atomic metadata protocol. Choose based on mutation granularity, namespace, coordination, and durability semantics, not the cheapest price per gigabyte.

References