Skip to content

Artifact overflow to blob storage (SeaweedFS / S3)

When a step or run returns a large output, Ironflow can transparently move that payload out of the database and into a blob backend, leaving only a small reference behind. Your functions never see the difference — reads inflate the payload back automatically.

This guide shows how to enable overflow and point it at a self-hosted SeaweedFS S3 endpoint (or any S3-compatible backend).

How it works

step/run output blob backend
─────────────── ────────────
> threshold ──offload──▶ {"__blob__":true,...} ──▶ artifacts/{env}/{run}/{step}/v{ver}/output-{hash}
≤ threshold ──inline──▶ stored in the DB column
any read ◀──inflate── full bytes restored before your function sees it
  • Threshold-gated. Only outputs larger than the configured threshold offload. Everything else stays inline in the database.
  • Transparent. Functions, the dashboard, ironflow inspect, and event subscribers all receive the full output — the reference is resolved server-side.
  • Reads always inflate. Disabling offload later (threshold 0) does not break reads of outputs that were offloaded while it was on.

Single-node default: local filesystem

On a single node, overflow needs no backend configuration. Blobs are written to a blobs/ directory next to the SQLite database (the data directory). Overflow is still off until you set a threshold — see Enable overflow.

The local filesystem backend is for single-node deployments only: the files live on one node’s disk and are invisible to other nodes. A multi-node cluster must use a shared S3 backend (Ironflow refuses to start a cluster on the filesystem backend).

Enable overflow

Set a threshold. Outputs larger than it offload; the value accepts human-readable sizes (1MB, 512KiB, 4MB).

ironflow.yaml
spec:
blobs:
artifactThreshold: "1MB" # offload outputs larger than 1 MB

Or via environment variable:

Terminal window
IRONFLOW_ARTIFACT_THRESHOLD=1MB ./ironflow serve

An empty value or 0 disables offload (the default). The read/inflate path is always active regardless.

Point overflow at SeaweedFS

SeaweedFS exposes an S3-compatible API and is the recommended self-hosted backend.

1. Run SeaweedFS with the S3 gateway

Terminal window
# Single-binary dev/self-host: filer + volume + S3 API on :8333
weed server -dir=/data/seaweedfs -s3 -s3.config=/etc/seaweedfs/s3.json

Define an access key/secret and a bucket in the S3 config:

/etc/seaweedfs/s3.json
{
"identities": [
{
"name": "ironflow",
"credentials": [
{ "accessKey": "ironflow", "secretKey": "REPLACE_WITH_A_SECRET" }
],
"actions": ["Read:ironflow-artifacts", "Write:ironflow-artifacts", "List:ironflow-artifacts"]
}
]
}

Create the bucket once it is running:

Terminal window
weed shell <<< "s3.bucket.create -name ironflow-artifacts"

2. Provide credentials to Ironflow

The S3 driver reads credentials from the standard AWS environment variables:

Terminal window
export AWS_ACCESS_KEY_ID=ironflow
export AWS_SECRET_ACCESS_KEY=REPLACE_WITH_A_SECRET
# AWS_SESSION_TOKEN is also honored if your backend issues temporary creds

Never put credentials in blobs.url or commit them — they belong only in the environment (or your secret manager).

3. Point Ironflow at the endpoint

The blob URL is s3://{bucket}?endpoint={url}. The endpoint scheme selects TLS: https:// connects securely, http:// does not. region is optional.

ironflow.yaml
spec:
blobs:
url: "s3://ironflow-artifacts?endpoint=https://seaweedfs.internal:8333"
artifactThreshold: "1MB"

Or via environment:

Terminal window
export IRONFLOW_BLOB_URL="s3://ironflow-artifacts?endpoint=https://seaweedfs.internal:8333"
export IRONFLOW_ARTIFACT_THRESHOLD=1MB
./ironflow serve

SeaweedFS uses path-style addressing, which the driver detects automatically for non-AWS endpoints — no extra configuration needed.

Using AWS S3 or another provider instead

The same s3://bucket?endpoint=... URL works for any S3-compatible backend (AWS S3, MinIO, Cloudflare R2, Backblaze B2). Set endpoint to the provider’s S3 endpoint and supply the matching AWS_* credentials.

Configuration reference

YAML (spec.blobs) Environment variable Default Meaning
url IRONFLOW_BLOB_URL (empty → local filesystem) s3://bucket?endpoint=...&region=... selects the S3 backend
artifactThreshold IRONFLOW_ARTIFACT_THRESHOLD (empty → off) Size above which outputs offload (1MB, 512KiB, …)

Environment variables override the YAML values.

Operational notes

  • Multi-node requires S3. A cluster (external NATS) refuses to start on the filesystem backend — set an s3:// URL. Reads of previously-offloaded outputs need the shared backend too, so the requirement holds even with offload off.
  • Environment delete reclaims blobs eagerly. When you delete an environment, Ironflow sweeps all offloaded blobs for that environment from the blob backend after the database rows are removed. Blobs for runs and steps inside a live environment still accumulate — there is no per-run or per-step garbage collection. Manage lifecycle for long-running environments yourself (for S3, a bucket lifecycle policy).
  • Missing blobs surface explicitly. If an offloaded blob is gone from the backend, the read fails with an explicit “output unavailable” state (a non-retryable DataLoss), naming the missing key — never a silent or opaque error.
  • Metrics. When metrics are enabled, overflow records offloads, bytes offloaded, degrades (offload failed → written inline), backend errors, and unavailable (missing-blob) events. See Observability.