What does 'S3-compatible' storage mean?

S3 is Amazon's object storage service, and 'S3-compatible' means another service accepts the same API. The same SDKs, aws-cli and rclone work against it, with only the endpoint and the keys changed.

Updated 6 min read

Learning objectives

After reading this article you will be able to:

  • Understand what Amazon S3 is and how buckets, objects and keys work
  • Know what it means for a service to be S3-compatible and where differences appear
  • Connect an application to S3-compatible storage with boto3
On this page

Almost every project ends up storing files: profile pictures, attachments, exports, logs. Keeping them on the server's disk works until the first time you need to move machines, run more than one instance, or serve everything fast. That is where object storage comes in, and sooner or later someone says "just use S3".

S3 became so common that the name stopped meaning a single product. "S3" is also a way of talking to storage: an API that dozens of services implement. Understanding that difference keeps you from getting locked into one vendor and explains why the same code runs in very different places.

app.pyimport boto3s3 = boto3.client("s3",endpoint_url=…,aws_access_key_id=…,aws_secret_access_key=…)s3.upload_file(…)s3.list_objects_v2(…)s3.delete_object(…)Amazon S3s3.amazonaws.comCompatible services3.example.comLocal serverhttp://localhostchanges per targetsame everywhere
The same code talks to any compatible target; only the endpoint_url and the keys change.

What is Amazon S3?#

Amazon S3 (Simple Storage Service) is AWS's object storage service. It stores data as objects inside buckets. An object is a file plus its metadata (such as Content-Type). A bucket is the container for objects. For the underlying concept, read what is object storage.

Every object has a key, its unique identifier inside the bucket. A key like photos/2026/cat.jpg looks like a folder path, but the storage is flat: photos/2026/ is just part of the name (a prefix). To see how this differs from disks and file shares, read object vs block vs file storage.

An object is addressable by a URL made of the endpoint, the bucket name and the key, for example https://my-bucket.s3.us-west-2.amazonaws.com/photos/cat.jpg. By default, buckets and objects are private: only someone who has been granted permission can access them.

A few numbers from the official documentation, worth double-checking before you depend on them:

  • Designed durability of 99.999999999% (11 nines) and 99.99% availability over a year for S3 Standard, with copies across at least three Availability Zones.
  • Objects up to 48.8 TiB, uploaded through multipart upload in up to 10,000 parts of 5 MiB to 5 GiB.
  • Strong read-after-write consistency: after a successful PUT, any read or list sees the new data.

What does "S3-compatible" mean?#

S3 is accessed through a REST API over HTTP. Every SDK, the aws-cli and tools like rclone just build requests in that format and sign them with a key pair. If another service understands the same requests, it is S3-compatible.

In practice, switching providers becomes configuration:

  1. The endpoint changes: instead of s3.amazonaws.com, the other service's address.
  2. The access keys (access key and secret key) become the new service's.
  3. The upload, download, list and delete code stays the same.

That is why backup tools, CMSs, upload libraries and frameworks support S3 and, with no extra work, any compatible service. The reverse holds too: if you write your code against the S3 API, you can move providers without rewriting the application.

What differs between S3 and a compatible service?#

"Compatible" is not "identical". The S3 API is huge and each provider implements a subset. The core usually exists everywhere: create bucket, PutObject, GetObject, ListObjectsV2, DeleteObject, multipart upload and presigned URLs. These vary, so check the provider's documentation:

  • Access control: S3 bucket policies, IAM and ACLs may be missing or behave differently.
  • Advanced features: versioning, Object Lock, replication, event notifications and lifecycle rules.
  • Regions and storage classes: a smaller provider may have a single region and a single class.
  • Limits: maximum object size, minimum part size in multipart, number of buckets.
  • Addressing: some services accept the bucket in the host (bucket.endpoint), others only in the path (endpoint/bucket).
  • Checksums: recent AWS SDK versions started calculating checksums by default, and some compatible services do not accept that yet (see the example below).

How do you connect an app to S3-compatible storage?#

The example uses boto3, the AWS SDK for Python. Install it with pip install boto3. The endpoint and keys come from environment variables, never from the code.

python
import os

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url=os.environ["S3_ENDPOINT"],
    aws_access_key_id=os.environ["S3_ACCESS_KEY"],
    aws_secret_access_key=os.environ["S3_SECRET_KEY"],
    region_name=os.environ.get("S3_REGION", "us-east-1"),
    config=Config(
        # "path" puts the bucket in the URL path; "virtual" puts it in the host.
        s3={"addressing_style": "path"},
        # SigV4 signing, the current version, presigned URLs included.
        signature_version="s3v4",
        # Turns off the automatic checksums from boto3 1.36+ for services
        # that do not accept them yet.
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

bucket = os.environ["S3_BUCKET"]

s3.upload_file("report.pdf", bucket, "reports/2026/report.pdf")  # upload

resp = s3.list_objects_v2(Bucket=bucket, Prefix="reports/")  # list
for obj in resp.get("Contents", []):
    print(obj["Key"], obj["Size"])

url = s3.generate_presigned_url(  # temporary download link, 15 minutes
    "get_object",
    Params={"Bucket": bucket, "Key": "reports/2026/report.pdf"},
    ExpiresIn=900,
)
print(url)

Four things in here tend to cause trouble:

  • addressing_style: the default (auto) lets boto3 choose. Against AWS it usually picks the virtual style; with a custom endpoint_url, current versions use path style. Setting path explicitly, as in the example, avoids surprises; if the provider requires the bucket in the host, use virtual. The boto3 documentation describes the values auto, path and virtual.
  • Signature: in several cases boto3 still generates presigned URLs in the old format (SigV2). signature_version="s3v4" forces SigV4, the current version, and many compatible services only accept that one.
  • Checksums: boto3 1.36 started calculating checksums on uploads by default. If your provider returns an error on PutObject, when_required restores the old behavior. If it accepts the new one, you can drop those two lines.
  • Region: compatible services usually ignore the region, but the SDK requires some value. us-east-1 is a common default.

The same applies to the aws-cli, which accepts --endpoint-url, and to rclone, which has an S3 remote type with an endpoint field. For temporary links, see what is a presigned URL. For large files, see how to upload large files.

When should you use S3 or a compatible service?#

S3-compatible storage fits user-uploaded images and videos, attachments, exports, data copies and the static files of a website. It fits poorly where you need ordinary file access, such as a database running on top of the disk, or small frequent writes to the same file: use a database or a block volume there. Also keep in mind that objects are replaced whole, not edited in place, and that latency is that of an HTTP request, not of a local disk.

When choosing between Amazon and a compatible service, compare the price of storage, requests and data transfer out (see what are egress fees), the region, and the features you actually use. If your code only uses the core of the API, switching later is cheap.

How to do this on Square Cloud#

Square Cloud Blob Storage is an S3-compatible service, and this article's code runs against it with configuration changes only, as the compatibility section described: S3_ENDPOINT=https://s3-blob.squarecloud.app, S3_REGION=auto and the S3 keys you derive from an API key in the "S3 access" tab of the dashboard. The same goes for the aws-cli with --endpoint-url, for rclone and for the AWS SDKs.

Before you migrate, check Blob against the list of what varies between providers. The endpoint supports List, Head, Get with Range, Put, Copy, Delete, multipart and SigV4 presigned URLs of up to 7 days. There are three fixed buckets per account: public, private and legacy (read-only). Since you can't create named buckets, set S3_BUCKET=public or private and organize files by prefix. Each object can be up to 10 GB, and multipart is only required above 100 MB. Beyond the S3 API, there is a REST API and a dashboard, with per-folder rules for visibility, expiration and caching.

On cost, there is no egress or ingress fee, and each plan includes a quota from 5 GB to 250 GB; S3 requests are rate-limited per plan. Durability is 99.999999999% (11 nines) with triple replication, and public files are served by a global CDN at the edge. Explore Blob Storage and compare quotas on Pricing.

Blob Storage

S3-compatible object storage with no egress fees

Learn more

FAQs

Is S3 the same thing as object storage?

No. Object storage is the type of technology. S3 is the Amazon service that popularized it and, by extension, its HTTP API, which many other services copied.

Can I use the AWS SDK with a service that is not AWS?

Yes, if the service is S3-compatible. You point the SDK at the service's address (endpoint_url) and use its keys. The rest of your code stays the same.

Does S3-compatible mean it has every S3 feature?

No. Almost every compatible service covers the basics (upload, download, list, delete, multipart upload, presigned URLs). Advanced features such as bucket policies, Object Lock or event notifications vary by provider.

What is the maximum object size on Amazon S3?

48.8 TiB, uploaded in up to 10,000 parts of 5 MiB to 5 GiB each. Compatible services have their own limits, so check the provider's documentation.

Next articleUploading large files: multipart and resumable uploadsMultipart upload splits a large file into parts that are sent in parallel and retried on their own. See the Python walkthrough, how to resume, and common mistakes.

More in Storage

See all 15 articles