S3 compatibility
Tested, not claimed.
SwiftFS claims compatibility only where tests prove it. Every operation marked Supported is exercised by automated tests using real clients:
- AWS SDK for Go v2 (
service/s3v1.114) over TLS, throughtests/integration(make test-integration). - minio-go v7.3 over plain HTTP, which uses per-chunk signed streaming, also in
tests/integration. - aws-cli 2.37, rclone 1.75 and s3cmd against a running server, through
tests/compat/run.sh(make test-compat). - AWS SDK for JavaScript v3 (3.1147) running a typical web-application flow (presigned browser upload with CORS, public media, private downloads,
lib-storagemultipart), throughtests/compat/js(make test-js).
Authentication
| Feature | Status | Notes |
|---|---|---|
| SigV4 Authorization header | Supported | Cross-checked against the AWS SDK signer; ±15 min clock skew |
| SigV4 presigned URLs (GET, PUT) | Supported | Up to 7 days. response-* overrides honored. |
UNSIGNED-PAYLOAD and signed SHA-256 payloads | Supported | SHA-256 verified before commit |
STREAMING-AWS4-HMAC-SHA256-PAYLOAD | Supported | Per-chunk signatures (minio-go, AWS published example) |
STREAMING-UNSIGNED-PAYLOAD-TRAILER | Supported | AWS SDKs' default for streamed uploads; trailer checksum verified |
STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER | Partial | Implemented, verified by unit tests; no client in the suite sends it yet |
| Signature Version 2 | Not supported | Deprecated by AWS; clients default to V4 |
| Anonymous access | Supported | Only where a bucket policy allows it (Principal: "*"). response-* overrides are refused for anonymous requests, as in S3. |
| STS / temporary credentials | Not supported | |
| POST Object (browser form upload) | Not supported | Planned:Use presigned PUT today |
Addressing
| Feature | Status | Notes |
|---|---|---|
Path-style (host/bucket/key) | Supported | |
Virtual-hosted style (bucket.host/key) | Supported | Enabled by SWIFTFS_S3_DOMAIN (needs wildcard DNS and TLS). Tested with the AWS SDK's default (UsePathStyle=false). |
Buckets
| Operation | Status | Notes |
|---|---|---|
| ListBuckets | Supported | prefix filter; returns all buckets in one page |
| CreateBucket | Supported | Location constraint must match SWIFTFS_REGION. Names are global across accounts. |
| HeadBucket | Supported | Returns x-amz-bucket-region |
| DeleteBucket | Supported | Must have no objects; in-progress multipart uploads are aborted |
| GetBucketLocation | Supported | |
| GetBucketVersioning | Supported | Always unversioned (empty configuration) |
| ListObjectVersions | Supported | Buckets are unversioned, so each object is listed as its only version, null, as S3 does for a bucket that never had versioning. prefix, delimiter, max-keys, key-marker, version-id-marker, encoding-type. versionId=null is accepted wherever a version ID is. |
| PutBucketVersioning | Not supported | Planned:V2 |
| Get/Put/DeleteBucketPolicy | Supported | IAM policy subset: Principal "*" only, Action/NotAction and Resource with wildcards, IpAddress/NotIpAddress on aws:SourceIp. Anything else is rejected (MalformedPolicy), never ignored. The owner can always manage the policy (lockout protection). |
| GetBucketPolicyStatus | Supported | IsPublic |
| Get/Put/DeleteBucketCors and OPTIONS preflight | Supported | S3 CORSConfiguration (≤ 100 rules, one wildcard per origin or header); CORS headers on actual requests, errors included: a request refused before its bucket is resolved (a bad or expired signature, a throttled key) still gets the bucket's CORS headers, so browsers can read the error (the lookup counts against the client IP's anonymous rate limit). Origins in SWIFTFS_CORS_ORIGINS (a management console) are allowed on every bucket after its own rules (an extension; S3 has no equivalent) |
| Lifecycle, tagging, encryption, website, logging, notifications, replication, object lock, ownership controls, public access block | Not supported | Planned:Lifecycle in V2 |
| Bucket ACLs | Not supported | Buckets behave as S3's default BucketOwnerEnforced |
Objects
| Operation | Status | Notes |
|---|---|---|
| PutObject | Supported | Up to SWIFTFS_MAX_OBJECT_SIZE (≤ 5 GiB). Content-MD5, x-amz-checksum-* (CRC32, CRC32C, CRC64NVME, SHA-1, SHA-256), x-amz-meta-* (2 KB), standard headers, x-amz-tagging stored |
Conditional PUT (If-None-Match: *, If-Match) | Supported | Evaluated atomically with the write |
| GetObject | Supported | Single byte ranges, partNumber, If-Match/If-None-Match/If-(Un)Modified-Since, response-* overrides, x-amz-checksum-mode |
| HeadObject | Supported | Same as GetObject, without a body |
| DeleteObject | Supported | Deleting a missing key returns 204 |
| DeleteObjects | Supported | Up to 1,000 keys; quiet mode; Content-MD5 or checksum verified; each key authorized separately |
| CopyObject | Supported | Within and across buckets of the same account; COPY/REPLACE metadata and tagging directives; x-amz-copy-source-if-* |
| GetObjectAcl | Partial | Returns owner FULL_CONTROL |
| PutObjectAcl | Partial | Accepts private and bucket-owner-full-control only (AccessControlListNotSupported otherwise, as S3 with ACLs disabled) |
| Multiple byte ranges in one GET | Not supported | Ignored (whole object returned), as in S3 |
| Object tagging API (Get/Put/DeleteObjectTagging) | Not supported | Planned |
| GetObjectAttributes, RestoreObject, SelectObjectContent | Not supported | |
| Server-side encryption (SSE-S3, SSE-KMS, SSE-C) | Not supported | Planned:V2. Requests asking for SSE are rejected, never silently stored unencrypted. |
| Object Lock, retention, legal hold | Not supported | Planned:V2 |
Storage classes other than STANDARD | Not supported | InvalidStorageClass |
Listing
| Operation | Status | Notes |
|---|---|---|
| ListObjectsV2 | Supported | prefix, delimiter, max-keys (≤ 1000), continuation-token, start-after, fetch-owner, encoding-type=url |
| ListObjects (v1) | Supported | marker, NextMarker with a delimiter |
| Byte-order key listing including Unicode | Supported |
Multipart uploads
| Operation | Status | Notes |
|---|---|---|
| CreateMultipartUpload | Supported | Metadata, checksum algorithm and type (COMPOSITE, FULL_OBJECT) |
| UploadPart | Supported | Parts 1–10,000, ≤ 5 GiB each; re-upload replaces |
| CompleteMultipartUpload | Supported | Order, ETag, size and checksum validation; no data copied |
| AbortMultipartUpload | Supported | |
| ListParts | Supported | max-parts, part-number-marker |
| ListMultipartUploads | Partial | prefix, markers, max-uploads; delimiter returns NotImplemented |
| UploadPartCopy | Supported | With x-amz-copy-source-range; copy-source conditions; whole single-part sources re-verified |
| Automatic cleanup of abandoned uploads | Supported | After SWIFTFS_MULTIPART_EXPIRY |
Tools
| Tool | Verified operations |
|---|---|
| aws-cli 2.37 | s3 mb/cp/ls/sync/rm --recursive/rb/presign, 200 MiB multipart upload, parallel ranged download, s3api head-object/put-object with metadata, server-side cp, s3api put/get/delete-bucket-policy, put/get/delete-bucket-cors, upload-part-copy |
| rclone 1.75 | mkdir, copy, check (sizes and hashes), 200 MiB multipart, lsf -R, purge |
| s3cmd | mb, put, ls, get, del, rb |
| AWS SDK for Go v2 | Everything in the integration suite, including default integrity checksums and trailers |
| minio-go v7 | MakeBucket, PutObject (signed streaming, multipart), GetObject, ListObjects, RemoveObject |
| AWS SDK for JavaScript v3 | CORS and policy configuration, browser preflight and presigned PUT from an allowed origin, anonymous public read, refused private read, presigned download with response-content-disposition, lib-storage 20 MiB multipart, ranged reads, prefix listing |
Service protections
These are SwiftFS behaviors, expressed with S3 error codes so clients react correctly:
| Protection | Response |
|---|---|
| Rate limits per access key and per client IP (anonymous) | 503 SlowDown, which SDKs retry with backoff |
| Per-account quotas (stored bytes, objects, buckets) | 403 QuotaExceeded |
Error behavior
Errors use S3's XML format, codes and status codes. HEAD errors carry no body. Every response has x-amz-request-id, x-amz-id-2 and X-SwiftFS-Request-ID (all the same value, also present in the server log). Requests for features SwiftFS does not implement fail with NotImplemented (501) instead of being silently accepted.
Ceph s3-tests
Ceph s3-tests is the most widely used independent S3 conformance suite. make s3-tests runs it against a fresh server in CI, and fails when a test fails without a listed reason.
Of the 886 tests in the suite's S3 files (test_s3.py and test_headers.py, commit 5522d1c), 245 pass, 478 need a feature SwiftFS doesn't implement, 49 expect Ceph-only behavior, 14 meet a deliberate difference, 5 can't fail as written and 95 are skipped by the suite. 245 of the 259 tests that only use features SwiftFS implements pass (94.6%). Every failure has a reason in s3-tests.md. Last run: 2026-10-11.
Next to verify
- POST Object (browser form uploads) and cross-account bucket policy grants.
This page is generated from SwiftFS Core's compatibility document, which changes only when the tests do.