Skip to content

S3 Storage

By default, Chatto stores persisted assets (attachments, avatars, server branding images, and link-preview images) inside NATS JetStream object stores. This works well for small to medium deployments, but can put pressure on your NATS storage as usage grows.

Switching to an S3-compatible backend offloads persisted asset storage to a dedicated object store while keeping all other data (messages, users, rooms) in NATS.

  • New persisted assets go to S3 when configured
  • Existing assets stored in NATS continue to work — each asset remembers which backend stores its bytes
  • URLs don’t change — the storage backend is an internal detail; asset URLs always use the same format
  • S3 prefixes are movable — Chatto stores prefix-free asset keys, so you can move objects to a different S3 prefix and update config without rewriting Chatto metadata

This means you can enable S3 at any time without migrating existing data. Old NATS-stored files remain accessible alongside new S3-stored ones.

Set the storage backend to s3 and provide your bucket credentials:

Terminal window
CHATTO_CORE_ASSETS_STORAGE_BACKEND=s3
CHATTO_CORE_ASSETS_S3_ENDPOINT=s3.amazonaws.com
CHATTO_CORE_ASSETS_S3_BUCKET=chatto-assets
CHATTO_CORE_ASSETS_S3_PATH_PREFIX=production/chatto
CHATTO_CORE_ASSETS_S3_REGION=eu-central-1
CHATTO_CORE_ASSETS_S3_ACCESS_KEY_ID=your-access-key
CHATTO_CORE_ASSETS_S3_SECRET_ACCESS_KEY=your-secret-key

Chatto creates the bucket automatically on startup if it doesn’t exist.

SettingDefaultDescription
endpointS3 endpoint URL
bucketBucket name
path_prefixOptional object key prefix for all S3 assets. Leading/trailing slashes are ignored.
regionAWS region (optional for non-AWS services)
access_key_idAccess key
secret_access_keySecret key
use_ssltrueUse HTTPS for S3 connections
path_styleautoOverride URL addressing. By default, AWS S3 endpoints use virtual-hosted addressing and custom S3-compatible endpoints use path-style addressing.

Any service that implements the S3 API works with Chatto. Chatto uses path-style URLs by default for custom S3-compatible endpoints, which works with providers that don’t support virtual-hosted bucket URLs.

Terminal window
CHATTO_CORE_ASSETS_STORAGE_BACKEND=s3
CHATTO_CORE_ASSETS_S3_ENDPOINT=your-account-id.r2.cloudflarestorage.com
CHATTO_CORE_ASSETS_S3_BUCKET=chatto-assets
CHATTO_CORE_ASSETS_S3_ACCESS_KEY_ID=your-access-key
CHATTO_CORE_ASSETS_S3_SECRET_ACCESS_KEY=your-secret-key

You can switch from S3 back to NATS at any time — just change storage_backend back to nats. Existing S3 files remain accessible because each asset records its storage backend. New uploads will go to NATS. You can also change path_prefix after moving or copying the S3 objects to the new prefix. Chatto stores logical, prefix-free asset keys in NATS, so no Chatto metadata rewrite is needed.

Stay with NATS (the default) if:

  • Your team is small and file uploads are infrequent
  • You want the simplest possible setup with no extra services
  • Total attachment storage stays under a few GB

Switch to S3 if:

  • You expect significant file, image, or video uploads
  • You want to separate compute (NATS) from bulk storage
  • You need to leverage existing S3 infrastructure or CDN integration
  • You’re running NATS with replication — S3 avoids tripling storage costs for large files