Scrapeless Wiki

What Is S3-Compatible Storage? – Definition and How It Works

Informational P3 what is s3-compatible storage

Learn what S3-compatible object storage is, how keys and prefixes work, and how to lay out collected data in it.

S3-compatible storage is any object store that implements Amazon S3's HTTP API. Because the API became a de facto standard, one client library works against many providers and self-hosted systems.

1. Objects, Not Files

An object store is a flat key-value map from a string key to a blob plus metadata. It is not a filesystem.

Filesystem Object store
Directories Key prefixes only
Rename Copy then delete
Append Not supported
Partial write Not supported
Lock Not supported
List a directory List by prefix

The / in a key is a convention, not a structure. raw/2026-08-18/page.html is one key that happens to contain slashes, and "directories" are a listing convenience.

The consequences that bite: you cannot append to an object, and a rename costs a full copy.

2. Why It Suits Collected Data

  • Effectively unbounded capacity without capacity planning.
  • Low cost per byte, with cheaper tiers for archival.
  • Write-once, read-many matches raw payload storage exactly.
  • Durability across devices without your involvement.
  • Direct querying by engines that read objects in place.

Raw HTML and JSON payloads are the canonical fit: written once, occasionally reprocessed, never modified.

3. Key Layout Is the Design Decision

The key structure determines what is cheap to list and what is expensive to find.

raw/dt=2026-08-18/site=example.com/<sha256-of-url>.html.gz

Three properties make this work: date first so a day's data lists with one prefix, site second so a single source is isolable, and a hash of the URL as the filename so the key is deterministic β€” rewriting replaces rather than accumulating, which is what makes the write idempotent.

Avoid deep prefixes for their own sake, and avoid keys beginning with a random value if you need date-range listing.

4. Basic Operations

import boto3

s3 = boto3.client(
    "s3",
    endpoint_url="https://storage.example.com",   # non-AWS providers
)

s3.put_object(Bucket="collect", Key=key, Body=gzipped,
              ContentType="text/html", ContentEncoding="gzip")

obj = s3.get_object(Bucket="collect", Key=key)

paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="collect", Prefix="raw/dt=2026-08-18/"):
    for item in page.get("Contents", []):
        print(item["Key"], item["Size"])

Use the paginator rather than a single list call. A plain list returns a bounded page, and code that ignores the continuation token silently processes only the first slice β€” a classic partial-data bug.

5. Multipart and Large Objects

Objects above a threshold are uploaded in parts, which allows parallelism and retry of a single part rather than the whole transfer.

The operational detail: an abandoned multipart upload leaves parts that consume storage but appear in no listing. A lifecycle rule to abort incomplete uploads after a few days is the fix, and its absence is a common source of unexplained storage cost.

6. Lifecycle and Tiers

Lifecycle rules move or delete objects by age. A typical arrangement keeps recent raw payloads in standard storage, transitions older ones to a colder tier, and expires them after a retention period.

Set the retention deliberately. Raw payloads are irreplaceable when the source cannot be re-read, so an expiry rule is a decision about what you are willing to lose.

7. Consistency and Concurrency

Modern S3 and most compatible stores offer read-after-write consistency for new objects, so a read following a write returns the data.

What they do not offer is any locking. Two writers to one key means last-write-wins, with no error. Coordination must live outside the store β€” which is why deterministic keys and idempotent writes matter more here than in a filesystem.

8. Summary

S3-compatible storage is a flat key-value object store with an API that became a standard, offering cheap, durable, effectively unbounded capacity for write-once data.

Design the key layout deliberately β€” date prefix, then source, then a hash of the URL so writes are idempotent β€” page through listings rather than trusting a single call, add a lifecycle rule to abort incomplete multipart uploads, and coordinate concurrent writers outside the store, because it provides no locks.