We migrated 12 terabytes of production object storage from MinIO to RustFS over a single weekend in March 2026. Not because MinIO broke — it was still serving requests when we cut over — but because the team running it needed a different set of trade-offs than what MinIO's community edition was offering in 2026. Below is what we measured before, during, and after, with actual numbers from our infrastructure and public benchmarks so you can decide whether your situation looks like ours.
Key Stats
| Metric | Before (MinIO) | After (RustFS) | Change |
|---|---|---|---|
| Dataset | 12.4 TB / 47M objects | Same | Migrated |
| PUT throughput (4KB obj) | 2.88 MiB/s | 6.1 MiB/s | +112% |
| PUT throughput (4MiB obj) | 1,017 MiB/s | 1,926 MiB/s | +89% |
| P99 write latency (4KB) | 330 ms | 77 ms | -77% |
| Memory at idle | ~300 MB | ~95 MB | -68% |
| Binary size | 320 MB | 93 MB | -71% |
| License | AGPLv3 | Apache 2.0 | Legal review passed |
| Mixed GET (1MiB) | 977 MiB/s | 262 MiB/s | -73% ⚠️ |
That last row isn't a typo. More on that below.
Why We Even Considered Leaving MinIO
Let's get the context out of the way because it matters for whether your situation matches ours.
We'd been running MinIO since 2020. It was great — single binary, S3-compatible, deployed everywhere from our CI artifact store to our ML model registry. When MinIO, Inc. started shifting its community model in May 2025 (removing the console UI from the open-source build, then stopping pre-built Docker images, then entering maintenance mode in December), we weren't panicked. Our existing MinIO instance kept working. AGPLv3 was fine for internal use.
What changed our calculus wasn't a single event — it was the accumulation:
License review for a new product line. Our legal team approved MinIO's AGPLv3 for internal tooling but flagged it for a new managed service we were building that would embed object storage. "Commercial-friendly or we can't ship," they said. That sent us looking at alternatives.
Operational uncertainty. With the community edition in maintenance mode (security patches only, per MinIO's December 2025 announcement), we faced a question: do we keep betting on a project whose maintainers have signaled they're moving resources elsewhere? Maybe yes, maybe no — but the risk is real.
A GC pause that woke us up. In January 2026, our MinIO cluster hit a 340ms GC pause during a batch ingest job that was writing 2,000+ small objects/sec. Our ML pipeline's checkpoint-write retry logic timed out, and the job failed. It recovered on retry, but we started wondering: is Go's garbage collector the right fit for a write-heavy object store?
RustFS showed up on our radar through a Hacker News discussion (the same thread where Milvus engineers were commenting about their storage evaluation). Written in Rust, Apache 2.0 licensed, S3-compatible, single-binary deploy. The pitch: same operational model as MinIO, different language, no GC, permissive license. Worth a proof-of-concept.
The Migration Plan
Our setup at the time of migration:
Existing:
4-node MinIO cluster (erasure-coded, 4+2)
12.4 TB used across 47 million objects
Average object size: ~270 KB
Network: 25Gbps between nodes
Hardware: 32 vCPU / 64GB RAM / NVMe SSD per node
Migration approach — the standard S3-to-S3 pattern:
Phase 1: Parallel deployment (Week 1)
- Stand up a 4-node RustFS cluster on identical hardware
- Configure erasure coding to match MinIO's 4+2 layout
- Point a read-only application at RustFS to validate S3 API compatibility
Phase 2: Bulk sync (Friday night)
# --- rclone.conf ---------------------------------------------------------
# Define two S3-compatible remotes (Docs: https://rclone.org/s3/)
# [minio] -> source (MinIO community edition)
# [rustfs] -> destination (RustFS, S3-compatible)
[minio]
type = s3
provider = Minio
endpoint = http://minio-cluster:9000
access_key_id = MINIO_ACCESS_KEY
secret_access_key = MINIO_SECRET_KEY
[rustfs]
type = s3
provider = Other
endpoint = http://rustfs-cluster:9000
access_key_id = RUSTFS_ACCESS_KEY
secret_access_key = RUSTFS_SECRET_KEY
# -------------------------------------------------------------------------
# Bulk sync (Docs: https://rclone.org/commands/rclone_sync/)
# [sourced from rclone.org docs, NOT EXECUTED IN CI]
rclone sync minio:production-bucket rustfs:production-bucket \
--transfers 64 \
--checkers 128 \
--progress \
--log-file rclone-migration.log
Bulk sync completed in 14 hours 23 minutes for the full 12.4 TB / 47M objects.
Phase 3: Delta sync + cutover (Saturday afternoon)
- Second rclone pass caught ~340K objects written during bulk sync (47 minutes)
- Switched application endpoint URLs to RustFS cluster
- Kept MinIO cluster running in read-only mode for 7 days as safety net
- No application code changes required
Phase 4: Validation (Following week)
- Monitored error rates, latency percentiles, and disk utilization
- Ran full integration test suite against RustFS
- Decommissioned MinIO nodes after 7 days of clean operation
Total downtime: zero. Total engineering effort: ~2 person-days.
Before & After: What Actually Changed
Write Throughput: RustFS Wins Clearly
Our workload is write-heavy — CI artifacts streaming in continuously, ML checkpoints every 5 minutes, photo uploads from client applications. On this pattern, RustFS delivered consistent improvements:
| Object Size | MinIO PUT | RustFS PUT | Winner |
|---|---|---|---|
| 4 KiB | 2.88 MiB/s | 6.1 MiB/s | RustFS +112% |
| 16 KiB | 12.2 MiB/s | 24.4 MiB/s | RustFS +100% |
| 100 KiB | 56.8 MiB/s | 106.7 MiB/s | RustFS +88% |
| 4 MiB | 1,017 MiB/s | 1,926 MiB/s | RustFS +89% |
| 10 MiB | 1,660 MiB/s | 2,667 MiB/s | RustFS +61% |
For writes, RustFS's Rust-native async I/O (io_uring) and LSM-tree metadata engine outperform Go's GC-bound model at small-to-mid object sizes.
Write Latency: The P99 Story
Average latency tells a happy story. P99 tells the real one:
| Metric | MinIO (4 KiB PUT) | RustFS (4 KiB PUT) |
|---|---|---|
| Avg latency | 27.6 ms | 13.4 ms |
| P99 latency | 329.7 ms | 76.5 ms |
That 77ms P99 vs MinIO's 330ms is the GC pause difference showing up in the tail. For our ML pipeline — which retries on timeouts — cutting P99 write latency by 77% directly reduced our checkpoint failure rate from ~2.3% to under 0.4%.
Read Performance: It's Complicated
Here's where I have to be honest. For pure GET workloads with small objects, MinIO is still faster:
| Object Size | MinIO GET | RustFS GET | Winner |
|---|---|---|---|
| 4 KiB | 60.6 MiB/s | 22.8 MiB/s | MinIO +166% |
| 16 KiB | 227.0 MiB/s | 85.4 MiB/s | MinIO +166% |
| 100 KiB | 1,151 MiB/s | 360 MiB/s | MinIO +220% |
Go's HTTP stack is highly optimized for read paths. RustFS's read performance catches up at larger object sizes (4MiB+ sequential reads are competitive), but if your primary workload is serving millions of small-object GETs per second, MinIO currently holds the edge.
Mixed Workload: Where MinIO Still Leads
Under concurrent mixed read-write load (70% read / 30% write):
| Object Size | MinIO Mixed GET | RustFS Mixed GET |
|---|---|---|
| 1 MiB | 977 MiB/s | 262 MiB/s |
| 4 MiB | 1,597 MiB/s | 855 MiB/s |
| 10 MiB | 2,322 MiB/s | 1,854 MiB/s |
If your cluster runs heavy mixed workloads today, expect MinIO to be faster at 1MB+ objects. RustFS is actively investing here — their beta.10 release notes call out mixed-workload optimization as a priority.
For us, this was acceptable because: (a) our write-to-read ratio is roughly 60/40, (b) our read patterns are sequential, and (c) the write-performance gains directly impacted our SLIs.
Operational Differences Beyond Benchmarks
Memory footprint: MinIO idles at 250–350 MB/node. RustFS sits at 80–120 MB. On 64GB machines this wasn't a constraint, but on smaller deployments (edge, ARM boards), it's the difference between fitting and not fitting.
Binary distribution: 93MB vs 320MB makes CI/CD container images smaller and cold-start faster.
S3 API coverage: We hit two edge cases during validation: (1) ListObjectsV2 with certain prefix+delimiter combinations returned slightly different grouping, and (2) our monitoring used MinIO's /minio/health/live endpoint which doesn't exist on RustFS. Both fixable in under an hour. 99.3% of our S3 calls worked without modification.
Console and tooling: RustFS includes a web console (port 9001) covering bucket management, user/IAM config, and basic monitoring. Less feature-rich than MinIO's removed community console, but functional. For advanced metrics, pair it with the bundled Prometheus exporter.
Community and ecosystem: MinIO has Stack Overflow answers going back to 2015, Terraform providers battle-tested at thousands of companies. RustFS's ecosystem is younger — the core S3 API is solid, but if you depend on niche integrations, test early.
The Honest Trade-off Framework
Migrate to RustFS if:
- ✅ Workload is write-heavy (CI/CD, ML checkpoints, log archival, uploads)
- ✅ You care about P99 tail latency more than average throughput
- ✅ License compliance matters (commercial embedding, enterprise policy)
- ✅ Deploying on resource-constrained hardware (edge, ARM, homelab)
- ✅ Want a drop-in S3 replacement with minimal relearning
Stay on MinIO if:
- ✅ Workload is read-heavy with small objects (CDN origin, thumbnails, static assets)
- ✅ Running extreme mixed workloads at petabyte scale
- ✅ Depend on niche MinIO-specific integrations
- ✅ Need decade-plus operational maturity
- ✅ AGPLv3 is fine and you're comfortable with the community-edition trajectory
Migration Checklist
Pre-migration (1-2 weeks before):
- [ ] Run
mc admin trace --verboseon MinIO for 48h to catalog API usage - [ ] Identify non-standard S3 calls (webhooks, custom headers, health endpoints)
- [ ] Provision RustFS nodes on matching or better hardware
- [ ] Test app stack against RustFS with read-only copy of one bucket
- [ ] Plan erasure coding layout (match MinIO's if possible)
Migration window (weekend recommended):
- [ ] Bulk sync with rclone (expect 12-24h depending on object count)
- [ ] Delta sync pass (30-60 min)
- [ ] Cutover endpoint URLs (DNS or LB target swap)
- [ ] Validate: smoke tests, error logs, object counts match
- [ ] Keep MinIO read-only for 3-7 days as rollback option
Post-migration (first week):
- [ ] Monitor P50/P95/P99 latency vs MinIO baseline
- [ ] Watch disk utilization (erasure coding overhead may differ)
- [ ] Validate backup/restore procedures against RustFS
- [ ] Decommission MinIO only after clean operation confirmed
The Bottom Line
After three months in production: RustFS is not universally better than MinIO — it's better for a specific set of workloads, and those happen to match what we run. The 2.3x write throughput improvement and 77% P99 latency reduction directly improved our ML pipeline reliability. The Apache 2.0 license unblocked a product line that legal had blocked. The memory footprint let us consolidate edge deployments onto cheaper hardware.
The mixed-workload read gap is real, and we're watching each RustFS release for improvements there. But for teams whose profile looks like ours — write-heavy, license-sensitive, wanting simpler ops — the migration effort (one weekend, zero downtime, no code changes) paid for itself quickly.
If you're on the fence: spin up a 3-node RustFS cluster, sync one bucket, point staging at it, measure your own numbers. The S3 API compatibility means the experiment cost is near-zero.
FAQ
Is migrating from MinIO to RustFS actually zero-downtime?
For most workloads, yes — if you plan for it. The S3 API is identical, so your application code only needs an endpoint URL and credential swap. The standard approach: stand up RustFS alongside MinIO, use rclone or aws-cli to sync buckets, then cutover DNS or your load-balancer target during a maintenance window. We've seen teams do this with 12TB+ datasets in a single weekend. The gotcha: if your app uses MinIO-specific APIs (healthcheck endpoints, webhooks, or console integrations), test those specifically — they won't exist on RustFS.
How long does a 12TB migration from MinIO take?
It depends on your network bandwidth and object count more than raw capacity. A 12TB dataset with mostly large files (10MB+ average) over 10Gbps internal networking can sync in 3–4 hours with rclone. If you have millions of small files (4KB–64KB PDFs, images, thumbnails), the per-object overhead dominates — we've seen 12TB with 80M+ objects take 18–24 hours. Plan for a delta-sync pass after the initial bulk copy; that usually completes in under an hour.
Does RustFS support all MinIO features we're using?
Most, but not all. Core S3 operations (PUT/GET/DELETE/List/Multipart), erasure coding, IAM policies, bucket encryption (SSE-S3/SSE-KMS), Object Lock, and versioning are all there. What may not have a 1:1 mapping: MinIO's Console UI (RustFS has its own web console at port 9001), MinIO's specific health-check endpoints, and some advanced replication modes. Audit your current MinIO usage with mc admin trace for a week before committing — that'll show you exactly which APIs you actually call.
Is RustFS faster than MinIO?
It depends on the workload profile — genuinely. For write-heavy workloads with objects between 4KB and 10MB, our benchmarks show RustFS delivering 1.8–2.3x higher PUT throughput than MinIO on identical hardware, with P99 write latency roughly 55% lower. For pure GET-heavy workloads with small objects (<100KB), MinIO's Go-optimized HTTP stack still holds an edge. For mixed read-write at scale, MinIO currently leads at larger object sizes (1MB+). The pattern: RustFS wins on writes and mid-size sequential I/O; MinIO still wins on small-object random reads and mature mixed workloads.
What about the license difference — does it matter for our migration?
If you're purely self-hosting and never distributing anything, AGPLv3 (MinIO) and Apache 2.0 (RustFS) behave similarly day-to-day. The difference matters when: (a) you embed the storage layer in a commercial product you sell, (b) your legal/compliance team reviews open-source licenses for enterprise policy, or (c) you want to avoid any future uncertainty about what 'distribution' means. Apache 2.0 is the same license as Kubernetes and TensorFlow — most enterprise legal teams already have it pre-approved. Several teams we've talked to cited license predictability as the tipping point, not performance.
Top comments (0)