show your work · S3 compatibility

We publish
the tests we fail.

Every vendor says “S3-compatible.” Almost none will show you where that stops. XNS runs 630 tests from the public ceph/s3-tests suite head-to-head with AWS S3, Ceph, MinIO, Wasabi, B2 and Storj, and publishes the result line by line in the matrix below — passes and failures alike. No rounding, no blended runs, no buried footnotes. Every caveat gets its own section instead of an asterisk. Check the operations your software actually calls, not the label.

build 13175be2 · scope v3.0 (630 tests) · 2026-08-14 · full breakdown ↓

XNS S3 Gateway · Compatibility

S3 feature support, line by line, against the field.

Every S3 capability that matters — core data path, versioning & WORM, lifecycle, encryption, identity, replication, tooling — measured for the XNS S3 Gateway against six object stores buyers compare it to — plus the original MinIO-based Relayer gateway (MinIO 2020) it replaced. Competitor cells come from each vendor's own documentation; the OLD-XNS column is from a code and live audit of the 2020 MinIO fork we retired.

Full Partial / caveats Not supported N/A to model ? Undocumented
Expand all Collapse all
FeatureXNSS3 GatewayAWS S3referenceCephRadosGWMinIOcommunityOLD-XNSMinIO 2020Wasabihot cloudB2BackblazeStorjDCS
Core object operations details →
PUT / GET / DELETE object
Multipart upload
Server-side CopyObject
Range GET (partial content)
Conditional requests If-Match / If-None-Match?
Max object sizeNo RAM cap48.8 TiB~5 TB5 TiBRAM-bound5 TB10 TBNo cap
Buckets per accountUnlimited10,0001,000UnlimitedUnlimited1,000100100
Buckets & listing details →
Create / Delete bucket
ListObjects v1
ListObjects v2
Prefix + delimiter
Versioning & data protection details →
Bucket versioning
Delete markers
Object Lock — governance
Object Lock — compliance / WORM
Legal hold
MFA delete?
Lifecycle & tiering details →
Lifecycle expiration
Lifecycle transitions to colder tiers
Noncurrent-version expiration
Multiple storage classes
Encryption details →
SSE-S3 server-managed keys
SSE-KMS external key management§
SSE-C customer-provided keys
Bucket default encryption
TLS in transit
Access control & identity details →
Bucket policies
Object / bucket ACLs
IAM users / access keys
IAM groups / roles
STS temporary credentials
Public Access Block
Presigned URLs
Replication & geo-distribution details →
Bucket replication S3 CRR / SRR
Geo-distributed data
Integration & tooling details →
AWS CLI
Modern AWS SDK current boto3
Virtual-hosted-style URLs
Path-style URLs
CORS configuration
Object tagging
Bucket tagging
Event notifications
Server access logging?
Metrics / observability
S3 Select§?
Inventory reports§
Requester Pays§?
Transfer acceleration§?
Platform & posture
Tenancy modelMulti (tenant) †MultiMultiHybridSingleMultiMultiMT / ST
Distributed erasure coding
Self-hostable
Deployment modelSelf-hostSaaSSelf-hostSelf-hostSelf-hostSaaSSaaSSaaS/Self
ceph/s3-tests publishedYesReferenceAuthors suiteNoNoNoNoNo
Multi-tenant, cost_center-scoped — not AWS-style cross-account IAM federation (different axis, out of model). See "Multi-tenant by architecture" below.
Own IAM/STS/metrics model — intra-account enforcement proven, not 1:1 AWS-policy parity. See "Identity & IAM" below.
§Deliberately out of model — see "What we don't implement, and why" below.
Single erasure-coded tier (80 data + 40 parity across up to 120 hosts) — see "Storage architecture" below.

How we measure this

Methodology. We run the public ceph/s3-tests conformance suite against every build, publish the counted-scope rate, and segment every non-passing test in the table below — nothing is rounded off the page. 79.1% (478 / 604 counted tests), scope v3.0, build 13175be2, 2026-08-14 — the subset XNS holds itself liable for. STS is now exercised by the conformance suite; current failures are error-response formatting, not missing capability.
Why the counted-scope denominator is 604. Scope v3.0 covers 630 ceph/s3-tests node-ids — expanded from the prior 549-test scope to include the full IAM/STS surface and additional data-plane tests. The counted denominator is 604: 630 minus 26 rows the ledger (v2.3) excludes as out-of-model, each with a cited reason. No exclusion is carved out by fiat; every non-passing test in the counted set is accounted for in the segmentation table below.
OLD-XNS (MinIO 2020). The comparison column is the vendored MinIO fork in gateway mode that the current XNS gateway replaced. Cells are from a code + live audit (2026-07-10), not vendor docs. Its "returns 200 but does nothing" traps — bucket versioning, ACLs, retention GET — are marked ✗ with the reason, because a success response there is worse than an honest error.

Unlike most of this field, we publish the counted-scope rate and the full non-passing breakdown — with run provenance immediately below.

The 126 non-passing counted tests, segmented — reproducible from the same ledger row cited below

SegmentCountWhat it is
Under investigation45Tests that passed on the prior build and now fail — candidate regressions from the 08-12/13 gateway merges, not yet root-caused.
STS, error-envelope formatting34The conformance suite now exercises STS directly; current failures are error-response formatting (missing Code element in the error envelope), not missing capability.
Genuine gap18Real failures — capability not yet implemented or not fully conformant.
Architecture-divergent, counted18SSE-C and related tests — by-design architecture difference, still counted in the denominator.
Intentional divergence4XNS is deliberately stricter than the ceph reference — see "What we chose to be different about" below.
Other5Deprecated AWS API behavior (3), harness artifact (1), newly scoped (1).
Not run this pass2

These seven rows sum to the 126 non-passing tests behind the 478 / 604 counted-scope figure above. This is the whole gap — nothing is rounded off the page.

Source: ceph/s3-tests run qa223-full-20260814-1109, build 13175be2, 2026-08-14, single run, no cross-run blending, reproduced zero-diff by an independent same-day cycle. Competitor figures from each vendor's official documentation, researched 2026-06-14.
79.1% counted scope (478 / 604) — scope v3.0 (630 tests, 604 counted), the tests XNS holds itself liable for.
Classification source: our per-test verdict ledger (v2.3 — 630 node-ids, 604 counted).
Note: support reflects each product's S3 API surface; managed-console features and non-S3 native APIs are noted as partial where they exist outside the S3 protocol.

Who’s actually behind the API

Multi-tenant by architecture. Identity is our own model.

Two markers on the matrix above († tenancy, ‡ identity) point here. Both are real, enforced capability — not caveats.

Tenancy: multi-tenant, cost_center-scoped

XNS is a multi-tenant distributed S3 gateway. Per-tenant isolation, storage quotas, billing rollups, and audit scoping are real and enforced on the admin plane (:9101) — proven by a two-tenant isolation test suite covering object-lock/WORM. Buckets are private by default; public read access requires an explicitly enabled bucket policy. AWS-style cross-account IAM principal federation is a different axis from tenant isolation and remains out of model.

Identity & IAM: our own model

XNS enforces its own identity model rather than 1:1 AWS-IAM-policy parity — intra-account enforcement is proven by the test suite. STS is capability-complete: AssumeRole (RoleArn trust-policy evaluation, ExternalId confused-deputy guard), AssumeRoleWithWebIdentity (JWKS-verified OIDC trust chain), GetSessionToken, and GetCallerIdentity are all implemented. Session-token enforcement is a uniform 403 across all four signing paths, constant-time compare, never logged.

STS: an asterisked pass, not an asterisked fail

Federation works. A stock AWS SDK calling sts:AssumeRoleWithWebIdentity with a token from your OIDC provider gets back temporary credentials exactly per the AWS wire spec — signature, issuer, audience, and expiry verified against the IdP's JWKS, trust-policy chain evaluated, session policies enforced as a ceiling. That's the capability customers mean when they ask "do you support STS," and the answer is yes.

The matrix marks STS ✓. STS is implemented (AssumeRole, AssumeRoleWithWebIdentity, GetSessionToken, GetCallerIdentity) and the conformance suite now exercises it directly — the earlier harness-reachability gap that blocked most STS tests is resolved. Current failures are error-response formatting (the response is missing the Code element the AWS error contract requires), not missing capability. The same four STS operations are exercised and passing in the separate XNS capability test suite. See the segmented breakdown in the matrix above.

Why we built it this way

The gateway is single-account by architecture — one owner per relayer, tenants scoped by cost center, not AWS-style sub-accounts. An IAM control plane that provisions and manages thousands of accounts solves a problem XNS doesn't have; carrying one would add exposed surface with no benefit to the box owner. We kept the wire-compatible federation data path and replaced AWS's IAM-API provisioning step with a single admin call: the box owner registers an OIDC identity provider once via POST /admin/v1/idp. After that, a stock AWS SDK federates identically to AWS.

The honest boundary

What we deliberately don’t implement, and why.

The § marker on the matrix above points here. These are edge S3 surfaces XNS holds out of model on purpose.

Out of model — no plan to build these

SSE-KMS (external key management — XNS's shard distribution is the key story, see Storage architecture below), S3 Select, Inventory reports, Requester Pays, and Transfer Acceleration are all marked N/A on the matrix, not partial. SigV2 signing is likewise excluded — AWS itself deprecated it.

SSE-C — we never take your key

SSE-C is marked N/A by design, alongside the items above. It asks you to send your AES-256 key in a header on every request. XNS already encrypts every shard with XChaCha20 before it leaves the gateway, on every upload, with no header to set — so a key you mail us adds nothing and costs you custody of it. Requests carrying SSE-C headers get a clean 501, never a silent no-op. To hold a key yourself, encrypt before uploading: we store the ciphertext and never inspect it.

Reading the gaps honestly

Some gaps are architecture, not absence.

The ceph/s3-tests suite was written against AWS S3 — a multi-tenant, multi-region, replication-first system. XNS is none of those things by design. Several features the suite tests are genuinely not applicable to our storage model, and a few represent an intentionally different mechanism that delivers the same or stronger outcome.

Architectural difference

Distribution over encryption keys

SSE-S3 and SSE-KMS presuppose a central key holder — the server encrypts, the server holds the key, you trust the server. XNS shards each object across 120 hosts: no single host ever holds a reconstructable object. Distribution is the encryption story. Adding a centralized key layer would introduce a weakness the architecture doesn't have.

Architectural difference

Erasure coding over bucket replication

S3 CRR/SRR exists because S3 stores your object once and needs explicit copies for redundancy. XNS stores 80 data + 40 parity shards across 120 independent hosts at write time. Geo-distribution and N+M redundancy are inherent, not a policy you configure. There is no single copy to replicate from.

Architectural difference

Single durable tier

Storage-class tiering — Standard to IA to Glacier — exists because HDD/tape economics made cold storage meaningfully cheaper on centralized infrastructure. On a distributed commodity network, "colder = cheaper" is an artificial distinction. There is one tier, durably erasure-coded, with no retrieval latency cliff.

Config and delivery both live

Event notifications & access logging

Config CRUD for both is real — GetBucketLogging/PutBucketLogging and GetBucketNotification/PutBucketNotification persist actual configuration, not stubs. Delivery runs too: webhook notifications ship AWS-format S3 event JSON — signed, retried with backoff, SSRF-guarded — alongside a Kafka publisher, and a background worker delivers access-log files into the target bucket the way S3 server access logging does.

Declaration API complete; encryption always on

Encryption at rest (SSE-S3)

The SSE-S3 API round-trips — the AES256 bucket default is accepted, persisted, and reflected correctly. On disk, every shard is encrypted with XChaCha20 before it leaves the gateway, always, with nothing to configure — the declaration doesn't change that because there is no unencrypted mode to upgrade from. The matrix marks the cell partial because the declaration and the storage cipher are independent layers, not because data sits unprotected. TLS in transit is complete for every competitor and for XNS.

A deliberate strictness posture

What we chose to be different about.

4 of the 126 non-passing counted tests aren’t gaps — they’re the ceph reference suite expecting AWS’s looser default, and XNS refusing to give it. We built these on purpose, out of the 2026-08 product-security work, and we’d make the same call again.

Anonymous-access tightening

ceph/s3-tests expects several anonymous-request paths to succeed by AWS default. XNS's private-by-default posture rejects them unless a bucket policy explicitly opts in. The test reads as a failure; the behavior is the intended one.

Existence-hiding (403, not 404)

XNS returns 403 rather than 404 for objects/buckets an unauthenticated caller shouldn't be able to confirm exist. The ceph suite expects 404. Not leaking existence to an unauthenticated caller is the stronger behavior.

CORS wildcard refusal

Where the suite expects a permissive wildcard CORS response, XNS refuses it. A gateway that will reflect any origin back is not a safer default — it's a wider one.

Why we publish this

Nobody else shows you their number.

Look at the last column of the matrix. MinIO, Wasabi, Backblaze B2, and Storj all show “No” next to “ceph/s3-tests published.” AWS is the reference the suite was built against. Ceph authors it. Everyone else runs it internally, curates the result, and quotes compatibility in marketing copy. We run it publicly against every build, publish the counted-scope number, and segment every one of the 126 non-passing tests instead of dropping them from a denominator. The score isn’t the story — the segmentation table is.

S3-compatible storage you can verify.

Change one endpoint. Every tool that speaks S3 already works — and you can audit the conformance yourself.

Evaluating this for backup or disaster recovery? We have already done that projection — every row above sorted by whether it touches a backup workflow.


Claims on this page last verified
© Copyright - SCP, Corp | Xa Net Services and Affiliates