---
title: "S3 is no longer (just) Amazon: alternatives, prices, and the cost of getting data back"
description: "The S3 API outlived MinIO's exit. Ceph, SeaweedFS, and Garage step in, and the real bill hides in the price of retrieving data."
date: 2026-09-27
locale: en
summary: "The S3 API has been frozen since 2006 and became the common language of storage. MinIO, the self-hosted reference, was archived in 2026; Ceph RGW (maturity), SeaweedFS (the broadest S3 subset), and Garage take over. On the bill, the trap is retrieval: a TB from Deep Archive costs over $100 to bring back, while R2 and B2 charge nothing for egress."
url: https://escribano.dev/en/blog/018-s3-compatible-object-storage/
---
Open the docs of any tool that touches storage: rclone, restic, Kopia, Duplicati, Cyberduck, PhotoPrism, Forgejo. The same expression shows up on the configuration page every time: *S3-compatible*. The same goes for the website of any object storage provider that has appeared in the last decade. One API became the industry's default language, and how it got there says a lot about how standards are won.

The trivia question is usually asked the other way around: what was AWS's first service? The instinctive answer is S3, and it is wrong. Amazon SQS opened its beta in late 2004, a year and a half earlier. S3 launched on March 14, 2006, was the first to reach general availability, and EC2 arrived later that same year. S3 was the second service to exist and the one that lent its name to all the rest.

## An API frozen in time

The original announcement was one paragraph long: *storage for the Internet*. The system started with roughly one petabyte of capacity spread across about 400 storage nodes, objects capped at 5 GB, and a price of 15 cents per gigabyte per month. The web console did not exist until 2010: for the first years, using S3 meant writing code or installing a third-party tool.

Twenty years later, the API version listed in the documentation is still `2006-03-01`. In its anniversary post, AWS highlights this: the code you wrote against S3 in 2006 works today, unchanged. The service grew by addition (objects up to 50 TB, storage classes, more than 500 trillion objects) while the basic vocabulary stayed still. That stillness is what made everything else possible.

## Protocol and product share a name

When someone says S3, they may be naming two different things. The product: the AWS platform, with its exclusive features (lifecycle to cold tiers, replication, event notifications, Object Lock, tight IAM integration). The protocol: the HTTP vocabulary any client can speak (buckets, objects, PUT/GET/DELETE, multipart uploads, SigV4 signing).

The *S3-compatible* label on those websites means, in practice, speaking the protocol with more or less product on top. That is the detail worth checking before choosing: clients that use the core vocabulary work against nearly any backend, while clients that depend on product features only work against AWS and the few providers that replicate them.

Some examples of that periphery, the part that falls off the edge:

* Backblaze B2 reduces ACLs to two values (private or public) at the bucket level, with no object tagging and no website configuration.
* Hetzner keeps the most conservative subset: no replication, no website, encryption only with SSE-C.
* Cloudflare R2 leaves out Lambda-style notifications and compensates with its own extensions (public buckets, Workers bindings).

A client like rclone (or restic, which only needs PUT, GET, and LIST with its own format on top) barely touches the core. That is why it works everywhere. A script leaning on replication or event notifications is already playing on AWS's court, endpoint notwithstanding.

## MinIO: the reference stopped

For a decade, if you wanted to speak S3 without a cloud, there was one answer: MinIO. A single Go binary exposing the full API on top of your own disks. The reference for testing, development, and homelabs, and the proof that the protocol could run without AWS in the middle.

That reference aged overnight. The project moved to AGPLv3 in 2021, with an explicit warning about what that meant for anyone offering the service over a network with modified code. In December 2025 it entered maintenance mode: no new features, no pull requests, critical security evaluated case by case. In April 2026 the repository was archived and set to read-only. The community edition is now distributed as source code only (via `go install`), the official Docker images were retired, and the company points to AIStor, its commercial product in Free and Enterprise editions. A fork maintained by Chainguard exists, also in maintenance mode, and SeaweedFS's own README recommends RustFS (a Rust rewrite under the Apache 2.0 license with a byte-compatible on-disk format) for anyone who needs to migrate a MinIO installation as is.

The lesson weighs more than the project. The community treated MinIO as the cornerstone of the S3-compatible ecosystem, and the cornerstone turned out to be an owned product whose company, when the moment came, reserved the commercial road for itself. The API survived. The binaries, well.

## The succession: Ceph, SeaweedFS, and Garage

The gap is now covered by projects with different profiles and years of production behind them. With one warning first: *S3-compatible* is a spectrum, not a binary seal. None of the three implements the full API, and each one publishes its own. Garage keeps a public compatibility page, endpoint by endpoint, where everything unimplemented answers with an honest `501 Not Implemented`.

The veteran is Ceph RGW, Ceph's object gateway: a decade and a half of production on OpenStack and similar platforms, backed by the Ceph Foundation, Red Hat, and IBM, with Object Lock, encryption, IAM, and multisite. Its documentation speaks of a broad subset of the Amazon API. The price of that maturity is operations: a RADOS cluster with its OSDs demands a maintenance scale far beyond a Raspberry Pi.

SeaweedFS sits in the middle. Go, Apache 2.0, 34,000 stars, weekly release cadence, and the broadest S3 subset of the group: the gateway implements 73 bucket and object operations, IAM, STS, versioning, Object Lock with retention and legal hold, lifecycle, tagging, and CORS, with a compatibility suite in CI. Its honest note is in the README itself: MinIO tracked the AWS API closely, and SeaweedFS keeps working toward that level. The architecture asks for more pieces than a single binary (master, volume, filer, and gateway), although `weed mini` starts everything with one command for small setups.

Garage bets on the opposite. Rust, AGPL, a lightweight binary with no external dependencies, designed for small geo-distributed clusters: three nodes in three different homes replicating data over the Internet. Deuxfleurs has run it in production since its first release in 2020. Its S3 subset is the most conservative of the three: no versioning (in progress), no Object Lock, partial lifecycle, encryption only with SSE-C. Plenty for restic, rclone, or serving static websites; a dealbreaker for a platform that depends on versioning.

| Project | License | Strength | Caveat |
|---------|---------|----------|--------|
| Ceph RGW | LGPL2.1 | Maturity and multisite at scale | Demanding operations |
| SeaweedFS | Apache 2.0 | The broadest S3 subset | More pieces to maintain |
| Garage | AGPL | Lightweight and geo-distributed | No versioning or Object Lock |
| RustFS | Apache 2.0 | Direct drop-in from MinIO | 1.0 GA (September 2026) |

Two recent options orbit nearby: RustFS, which reached its 1.0 GA on September 16, 2026 after more than a year of public iteration, and VersityGW, a stateless gateway in Go (Apache 2.0) that exposes S3 on top of a POSIX filesystem, Azure, or another S3 backend, with conformance testing against the official AWS SDKs.

## The bills: cheap to store, expensive to recover

B2 and R2 compete with AWS on another axis: price, and specifically the line of the bill that appears when you ask for your data back.

AWS publishes storage by class, and that is where the first trap lives. The Standard class charges nothing for retrieval (the $0.023 per GB-month, about $23 per TB, is the cost of keeping). The classes that make storage cheaper place a toll at the exit door:

| AWS class | Storage ($/GB-month) | Retrieval ($/GB) | Minimum stay |
|-----------|----------------------|------------------|--------------|
| S3 Standard | 0.023 | free | none |
| Standard-IA | 0.0125 | 0.01 | 30 days |
| One Zone-IA | 0.01 | 0.01 | 30 days |
| Glacier Instant Retrieval | 0.004 | 0.03 | 90 days |
| Glacier Flexible | 0.0036 | 0.01 (bulk: free) | 90 days |
| Glacier Deep Archive | 0.00099 | 0.02 (bulk: 0.0025) | 180 days |

The fine print comes along: minimum storage duration billed if you leave early, a 128 KB minimum billable object size in the IA classes (a billion 4 KB files get billed as if they weighed 128 GB), request fees on top, and a restored Glacier archive billed as a temporary Standard copy while you download it.

On top of that comes traffic to the Internet: $0.09 per GB on AWS (the first 100 GB per month are free), free on B2 up to a limit of three times the average stored volume per month (then $0.01 per GB), and unconditionally free on R2.

The example that makes the difference visible: restoring a TB stored in Deep Archive via the standard route costs about $20 in retrieval, the temporary Standard copy (under a dollar a day), the requests, and about $85 more in egress if the final destination is your home. More than a hundred dollars to bring back what costs about a dollar a month to store. The same TB from B2 falls inside the free 3x rule (about $10 above it) and from R2 pays no egress; $10 only if it sat in the Infrequent Access class, the only one of the three that keeps a retrieval toll, announced and contained.

A direct comparison (per TB and month, published rates):

| | AWS S3 (Standard) | B2 | R2 (Standard) |
|---|-------------------|----|---------------|
| Storage | ≈ $23.5 | $6.95 | ≈ $15 |
| Egress to Internet | $0.09/GB | free up to 3x, then $0.01/GB | free |
| Cold tiers with a toll | $0.01 to 0.03/GB | no cold tiers | IA only: $0.01/GB |
| Requests | $0.005/1k writes, $0.0004/1k reads | free (class D at $0.004/10k after 2,500/day) | $4.50/M writes, $0.36/M reads |

And the European flat bundle sits outside the comparison by structure: Hetzner Object Storage sells a base quota with storage and traffic included, data in Falkenstein, Nuremberg, and Helsinki, in exchange for the most conservative S3 subset on the market (no replication, no website, SSE-C only), aimed at backups and file servers.

The real catalog is longer (Wasabi, DigitalOcean Spaces, Ceph RGW for those who want to run their own), but these cover the range of models: cheap archive, zero egress, the European bundle, and self-hosted.

## The same binary, another endpoint

The practical promise of the standard fits in one line:

```bash
aws s3 ls s3://my-bucket --endpoint-url https://<account_id>.r2.cloudflarestorage.com
```

The same CLI you use against AWS works against R2, B2, or Hetzner by adding one flag. With rclone the change is similar: configuring an `s3` remote only swaps endpoint, region, and keys; the rest of the pipeline (scripts, encryption, cron) stays intact. The effort of learning one tool pays off across all backends at once, which is exactly what a standard promises.

## Rock, paper, scissors

The [RPS framework](/blog/002-rps-principle/) orders the options by the level of complexity you are willing to maintain:

| | Approach |
|--|----------|
| **Rock** | One bucket on B2 or R2, restic or rclone, keys in the password manager. A remote copy you can actually restore. Or Garage on your own node if the data can live at home. |
| **Paper** | Two providers with the same tool, scripts parametrized by endpoint, and restores rehearsed now and then. Or SeaweedFS on three nodes to move storage to your own hardware without losing vocabulary. |
| **Scissors** | Ceph RGW with multisite, lifecycle to cold tiers, a CDN in front of the bucket, and full lifecycle automation. |

The bridge/anchor axis (which [I already explored with cloud-first](/blog/004-cloud-first-problem/)) fits here cleanly. Speaking S3 is the bridge: switching providers comes down to changing endpoint and keys, in either direction. The anchor shows up in three places. Coupling yourself to product features only AWS has (fine-grained replication, Object Lock, IAM) ties you to the vendor. Chaining the architecture to the hyperscaler's egress bill ties you to the platform, and it is precisely the anchor R2 turned into a selling point. And the retrieval toll of cold tiers is the silent anchor in the bill: it ties you to the provider's terms at the worst possible moment, the day you need the data. [Digital sovereignty](/blog/005-digital-sovereignty/) has a practical version here: data on Garage or Hetzner carries different weight than data on an AWS bucket, with the same vocabulary in between.

## The common language

The story has a pleasant irony. Amazon turned its API into the de facto standard and, for years, that worked as the gateway to a huge platform. MinIO built its position on the free part of that standard and, when it turned toward the commercial product, left the gap that Garage, SeaweedFS, and Ceph now fill. The protocol outlived both: by freezing the vocabulary and growing around it, it became free to copy, and every provider speaks it with its own accent.

Data can live in three different homes (Garage), in a serious cluster (SeaweedFS, Ceph), in a cheap archive (B2), or behind a network that does not charge for egress (R2), and the tools remain the same. The choice breaks down into two questions: which protocol your tools speak (S3, almost certainly) and how much it will cost to bring the data back the day you need it. The first decides which backends you can work with. The second decides how much it costs you to change your mind.

*Note: while this post was being revised, RustFS reached its 1.0 GA (September 16, 2026). Thanks to Lorenzo from [atareao.es](https://atareao.es/) for the heads-up.*
