How to configure S3 blob tiering#

This guide shows you how to configure tiered blob storage so that small blobs stay in PostgreSQL and large blobs go to S3.

Install the S3 extra#

pip install zodb-pgjsonb[s3]
# or
uv pip install zodb-pgjsonb[s3]

This installs the zodb-s3blobs dependency with the boto3 S3 client.

Add S3 configuration to ZConfig#

Add the S3 keys to your <pgjsonb> section in zope.conf:

%import zodb_pgjsonb

<zodb_db main>
    <pgjsonb>
        dsn dbname=zodb user=zodb host=localhost port=5432

        s3-bucket-name my-zodb-blobs
        s3-region us-east-1
        s3-prefix production/

        blob-threshold 100KB
        blob-cache-dir /var/cache/zodb-blobs
        blob-cache-size 1GB
    </pgjsonb>
</zodb_db>

S3 configuration keys#

Key

Default

Description

s3-bucket-name

none

S3 bucket name (setting this enables S3 tiering)

s3-region

none

AWS region name

s3-endpoint-url

none

S3 endpoint URL (for MinIO, Ceph, or other S3-compatible stores)

s3-access-key

none

AWS access key ID (uses boto3 credential chain if omitted)

s3-secret-key

none

AWS secret access key (uses boto3 credential chain if omitted)

s3-use-ssl

true

Enable SSL for S3 connections

s3-prefix

empty

S3 key prefix for namespace isolation

Blob storage keys#

Key

Default

Description

blob-threshold

100KB

Blobs larger than this go to S3

blob-cache-dir

auto

Local cache directory for S3 blobs

blob-cache-size

1GB

Maximum size of the local blob cache

Choose a blob-threshold strategy#

The blob-threshold setting controls how blobs are distributed between PostgreSQL and S3.

PG-only mode (no S3): Omit s3-bucket-name entirely. All blobs stay in PostgreSQL bytea columns regardless of size.

Tiered mode (default with S3): Set blob-threshold to a size like 100KB (the default). Blobs smaller than this stay in PostgreSQL for fast access. Blobs at or above this threshold go to S3.

S3-only mode: Set blob-threshold to 0. All blobs go to S3, keeping the PostgreSQL database compact.

Set up a local blob cache#

Set blob-cache-dir to a local directory for caching S3 blobs on disk. This avoids repeated S3 downloads for frequently accessed blobs.

Set blob-cache-size to the maximum disk space for the cache. The cache uses LRU eviction when the limit is reached.

For production, always configure a blob cache directory to reduce S3 latency and cost.

Use MinIO for development#

Start a MinIO container:

docker run -d --name minio \
  -p 9000:9000 -p 9001:9001 \
  -e MINIO_ROOT_USER=minioadmin \
  -e MINIO_ROOT_PASSWORD=minioadmin \
  minio/minio server /data --console-address ":9001"

Create a bucket:

mc alias set local http://localhost:9000 minioadmin minioadmin
mc mb local/zodb-blobs

Configure the storage to use MinIO:

<pgjsonb>
    dsn dbname=zodb user=zodb host=localhost port=5432

    s3-bucket-name zodb-blobs
    s3-endpoint-url http://localhost:9000
    s3-access-key minioadmin
    s3-secret-key minioadmin
    s3-use-ssl false

    blob-threshold 100KB
</pgjsonb>