Skip to main content

fast-s3

Download or upload very many small files to S3-compatible storage (AWS S3, Wasabi, MinIO, ...) from Python at rclone-like speed.

Transfers of small objects are bound by round-trip latency, so throughput is essentially concurrent requests / latency. fast-s3 keeps hundreds of requests in flight from a single process by talking to S3 directly over aiohttp with its own Signature V4 signing, which costs about 0.1 ms of CPU per object instead of the 2-4 ms that boto3 needs.

Setup

uv sync

Usage

Download files

from PIL import Image
import io
from fast_s3 import Fetcher, Status

large_list_of_keys = [...]

fetcher = Fetcher(
    paths=large_list_of_keys,
    endpoint_url="https://s3.my-path-to-s3",
    aws_access_key_id="my-key-id",
    aws_secret_access_key="my-secret-key",
    region_name="my-region",
    bucket_name="my-bucket",
    ordered=True,       # yield files in the same order as paths
    concurrency=256,    # requests in flight
    buffer_size=8192,   # max files downloaded ahead of the consumer (bounds memory)
    callback=lambda data: Image.open(io.BytesIO(data)),  # optional, runs in a thread pool
)

for file in fetcher:
    if file.status == Status.succeeded:
        file.content.save(file.path)
    else:
        print(file.path, file.exception)

callback receives the raw bytes of each object. Pass callback_executor=concurrent.futures.ProcessPoolExecutor(...) if it is CPU heavy pure-Python code that does not release the GIL.

Upload files

from fast_s3 import Uploader

with Uploader(
    endpoint_url="https://s3.my-path-to-s3",
    aws_access_key_id="my-key-id",
    aws_secret_access_key="my-secret-key",
    region_name="my-region",
    bucket_name="my-bucket",
    concurrency=256,
) as uploader:
    uploader.queue_upload(
        source=large_list_of_files,   # bytes, file paths, or file-like objects
        destination=large_list_of_keys,
    )
    results = uploader.await_upload()

Failed requests are retried with exponential backoff (n_retries, backoff_factor) on connection errors and 429/5xx responses. Errors are reported per file (file.status == Status.failed, result.status == "error"), never raised from the iteration.

Options

  • concurrency: number of concurrent HTTP requests (default 256). Raise it for high-latency endpoints; throughput grows almost linearly until you saturate your network link or the CPU (a few thousand files per second).
  • buffer_size: how many files may be downloaded ahead of the consumer, in flight or waiting. Defaults to 4 x concurrency, or 32 x concurrency when ordered=True. Ordered iteration stalls whenever one slow object has buffer_size finished files queued behind it, and some S3 services serve the occasional object in seconds instead of milliseconds, so a larger window buys throughput at the cost of memory (window x file size).
  • hedge: duplicate a GET that takes 5x longer than average (True, the default), after a fixed number of seconds (a float), or never (False).
  • addressing_style: "auto" (virtual-hosted when the bucket name allows it, like boto3), "path" or "virtual". Use "path" for endpoints without wildcard DNS.
  • verify_ssl: set to False for self-signed endpoints.
  • verbose: log retries and failures to stderr.

AsyncS3Client (get_object, put_object, head_object, delete_object) is also exported for use directly from asyncio code.

Benchmarking

benchmarks/compare_rclone.py downloads the same keys with Fetcher and with rclone copy and prints files per second for each:

uv run benchmarks/compare_rclone.py --keys-file keys.txt \
    --concurrency 64 256 512 --rclone-remote wasabi --rclone-transfers 64 256

benchmarks/compare_rclone_upload.py does the same for uploads into a bucket you name explicitly, and can delete what it uploaded afterwards:

uv run benchmarks/compare_rclone_upload.py --bucket my-dev-bucket --n 5000 \
    --concurrency 64 256 --rclone-remote wasabi --rclone-transfers 64 256 --cleanup

Both read credentials from STORAGE_ENDPOINT, STORAGE_ACCESS_KEY_ID, STORAGE_SECRET_ACCESS_KEY, STORAGE_REGION_NAME and BUCKET_NAME (a .env file is loaded if present).

Tests

uv run pytest

Integration tests need an S3 endpoint and are skipped unless FAST_S3_TEST_ENDPOINT, FAST_S3_TEST_KEY, FAST_S3_TEST_SECRET and FAST_S3_TEST_BUCKET are set (a local MinIO works well).

Metadata

Release files for fast-s3 4.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fast-s3 4.0.0
File Size Uploaded
fast_s3-4.0.0.tar.gz 11.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fast-s3 4.0.0
File Interpreter ABI Platform
fast_s3-4.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.2 kB

Release files / fast_s3-4.0.0.tar.gz

Download URL fast_s3-4.0.0.tar.gz
Size 11.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7602d0064de6c23d352330149799a5a2d407bf2f5de065f30c18cc516c429055
BLAKE2b-256 checksum
How to use checksums
ed886a8abd6d9959187ae83c19dfc6142469e5ef710c7a93a3f542a162794f9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / fast_s3-4.0.0-py3-none-any.whl

Download URL fast_s3-4.0.0-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
538b809b09f7ab5691362c702ac10160e54a7e44045cc236ea2c5fc7671ee2cd
BLAKE2b-256 checksum
How to use checksums
fc8eedc8bd65104d62e0af5ad42a50479413a0fc96d890432e0e42fe67705d05
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

4.0.0 This release

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page