Object storage, block storage, and file storage don't compete for the same job: each solves a different problem. Pick the wrong layer and you end up overpaying, fighting scale, or suffering latency where it hurts. This guide explains in depth how each model works, how data is accessed, what metadata and guarantees each one offers, and when each is the right choice, with concrete examples.
The three ways to store data
Every infrastructure ultimately rests on one of these three storage paradigms, or on a combination of all three. The difference isn't just "where" the bytes live, but the unit you work with and how you access it: disk blocks, files in a directory tree, or objects identified by a key. Understanding that unit is what prevents most architecture mistakes.
Block storage
Block storage exposes raw volumes that the operating system sees as disks. You format them (ext4, XFS, NTFS), mount them, and from there the storage is transparent: a database or a file system reads and writes fixed-size blocks at arbitrary positions on the volume. The device doesn't know what's inside each block; it only addresses sectors.
That closeness to the hardware is its great advantage. Random reads and writes are fast, latency ranges from microseconds to a few milliseconds, and you can guarantee sustained IOPS. In exchange, a volume is usually tied to a single machine and a specific availability zone: scaling means growing the disk or migrating it, not adding infinite capacity elastically.
- Access unit: the block, addressed by offset within the volume.
- Typical protocols: iSCSI, NVMe-oF, Fibre Channel, or the VM's virtual disks.
- Metadata: practically none at the block level; the meaning comes from the file system you mount on top.
- Strong point: low latency and random writes for transactional workloads.
- Limitation: bounded capacity per volume and coupling to a machine/zone.
File storage
File storage adds a layer of organization: files within a directory hierarchy, shared over the network through protocols like NFS or SMB/CIFS. Multiple clients can mount the same share and work with familiar paths (/datos/proyecto/informe.pdf), with POSIX permissions or ACLs and file locking to coordinate concurrent access.
It's the most intuitive model for humans and for legacy applications that expect a shared file system: home directories, team shares, legacy software that writes to paths. The price you pay is scale: the hierarchy and POSIX metadata become a bottleneck when you're dealing with hundreds of millions of files, and availability depends on the server or array that serves the share.
- Access unit: the file, located by its path within a directory tree.
- Typical protocols: NFS, SMB/CIFS.
- Metadata: POSIX/ACL permissions, timestamps, owner; rich for management, but rigid.
- Strong point: shared access and familiar file system semantics.
- Limitation: the hierarchy caps performance at very large scales.
Object storage
Object storage breaks away from the hierarchy. Each piece of data is an object: the binary content plus a set of metadata, identified by a unique key within a bucket. There are no real folders (what look like "directories" are simply prefixes in the key) and you don't mount anything: you access it over HTTP through the S3 API, with operations like PUT, GET, LIST, and DELETE.
That flat design is what allows near-unlimited scaling, from gigabytes to petabytes, spreading objects across many nodes without a hierarchical index that saturates. Durability is achieved with Erasure Coding: each object is split and encoded into redundant fragments spread out, so it can be reconstructed even if several disks fail. The trade-off is latency: an HTTP request over the network is in the range of tens of milliseconds, perfect for reading an entire file but unsuitable for the thousands of random writes per second a database demands.
In OtterStorage, objects live behind the https://es-mad-1.s3.otterstorage.io endpoint and you can choose your region: EU-MAD (Madrid), EU-FRA (Frankfurt), or US-EAST. An operation as simple as uploading an object looks like this with the AWS CLI:
aws --endpoint-url https://es-mad-1.s3.otterstorage.io \
s3 cp ./dataset-2026.parquet s3://datos-analitica/raw/dataset-2026.parquet
# List what's under a prefix (the "directories" are just keys)
aws --endpoint-url https://es-mad-1.s3.otterstorage.io \
s3 ls s3://datos-analitica/raw/
- Access unit: the object, located by its key within a bucket.
- Protocol: S3 API over HTTP/HTTPS, accessible from anywhere.
- Metadata: rich and extensible (Content-Type, ETag, and your own key-value pairs per object).
- Strong point: massive scale, high durability, and global addressing.
- Limitation: not suited for low-latency random writes or for mounting as a disk.
Metadata: the trait that sets object storage apart most
Where block storage barely keeps metadata and file storage sticks to POSIX attributes, object storage treats metadata as a first-class citizen. Each object can carry its own tags that you then use to classify, apply lifecycle rules, or filter. That turns the bucket into something closer to a data catalog than a disk:
aws --endpoint-url https://es-mad-1.s3.otterstorage.io \
s3api put-object \
--bucket datos-analitica \
--key informes/2026/q2.csv \
--body q2.csv \
--content-type text/csv \
--metadata proyecto=ventas,confidencialidad=interno,retencion=7y
Comparison table: object vs block vs file
| Criterion | Object storage | Block storage | File storage |
|---|---|---|---|
| Unit | Object (key + data + metadata) | Fixed-size block | File in a directory tree |
| Access | S3 API over HTTP | Mounted disk (iSCSI, NVMe-oF) | NFS, SMB/CIFS |
| Latency | Tens of ms (network) | Very low (µs to a few ms) | Low to medium |
| Scalability | From GB to PB, nearly unlimited | Bounded by the volume | Limited by the hierarchy |
| Metadata | Rich and customizable | Minimal | POSIX/ACL, timestamps |
| Random writes | No (whole object) | Yes, its strong point | Yes |
| Typical use case | Backups, media, datasets, logs | Databases, VM disks | Shared resources, home dirs |
When to choose each one
The right question isn't "which is best," but "what access unit does my workload need." A quick rule that almost never fails:
- A production database (PostgreSQL, MySQL, MongoDB) → block storage. It needs low-latency random writes and a mounted file system.
- Backups of that database → object storage, ideally with immutability. It reads and writes whole files and needs scale and durability, not IOPS.
- Images, videos, and your app's attachments → object storage, served through the S3 API.
- A VM's boot disk → block storage.
- AI datasets, data lakes, logs, and CI artifacts → object storage; these are unstructured data that grow without end.
- A share used by several teams with paths and POSIX permissions → file storage.
If your workload needs to modify small chunks of a huge file many times per second, it's block. If it works with whole files written once and read many times, and you want to stop worrying about capacity, it's object. If you need several machines to see the same folder tree with file system semantics, it's file.
The usual pattern: they complement each other
In practice, almost no architecture picks just one layer. The norm is to combine block for the hot data and object for the bulk: the database lives on a fast block volume and its copies travel to S3 with immutable retention. Backing up PostgreSQL to S3 is the canonical example: production on block, history on object.
On OtterStorage, that flow rests on concrete pieces. Immutable copies are protected with Object Lock (WORM) in Governance or Compliance modes, preventing ransomware or an accidental deletion from taking out your backups. Lifecycle rules move or expire objects based on their age, and versioning keeps previous versions of each object. And since we don't charge for requests or deletions, listing or rotating millions of objects doesn't blow up the bill.
{
"Rules": [
{
"ID": "expira-backups-antiguos",
"Status": "Enabled",
"Filter": { "Prefix": "backups/postgres/" },
"Expiration": { "Days": 90 }
}
]
}
Common myths
A few ideas circulate around these technologies that lead to bad decisions. These are the ones we see most often:
- "Object storage is just a slower network disk." It isn't a disk: it's an HTTP service with different semantics. You don't mount it or seek within an object; you work with whole objects identified by key.
- "I can run my database on S3." A transactional database needs low-latency random writes that object storage doesn't offer. The correct setup is the database on block and its copies on object.
- "Object storage is always cheaper." It depends on the access pattern. For large-volume unstructured data it usually works out better, especially if the provider doesn't charge for requests; for hot IOPS, block is the right tool. The cost-based choice makes more sense alongside our guide on how to reduce cloud storage costs.
- "Buckets have folders." There are none, really. The hierarchy is a convention over the key:
fotos/2026/playa.jpgis a single key with slashes, not nested folders. - "Object means I lose control over consistency and security." Quite the opposite: you have versioning, per-bucket Legal Hold, and access keys isolated per bucket to limit each credential's blast radius.
In summary
Block for what needs latency and mounting; file for sharing a tree of files; object for scaling and lasting. Most modern architectures use all three at once, each where it shines. If your case is backups, media, datasets, or logs, object storage is the answer, and migrating to it doesn't force you to change your tools: the S3 API is a standard that AWS CLI, rclone, Restic, Velero, and Terraform already speak. When you're ready to make the leap, the documentation has the guides to get you started in minutes.
Frequently asked questions
Can I use object storage as my server's disk? +
Is object storage slower than block storage? +
What's the difference between file storage and object storage? +
Your object layer, S3-compatible
Scale from GB to PB without changing your tools.
Hazte Founding Otter