Storage Configuration
Configure where Reflexio stores data, including SQLite (default), Supabase, and PostgreSQL for production deployments.
Storage Configuration
Storage configuration determines where Reflexio stores data.
Default Storage (Open Source)
The open-source version uses SQLite by default — no storage configuration is needed. Reflexio automatically creates and manages a local SQLite database, so you can start using it immediately without any setup.
# No storage configuration required — SQLite is used automatically
client = ReflexioClient() # see Quickstart for connection options
config = client.get_config()
# config.storage_config is already set to SQLitecurl -X GET "${REFLEXIO_URL:-https://www.reflexio.ai}/api/get_config" \
-H "User-Agent: my-agent-reflexio" \
-H "Authorization: Bearer $REFLEXIO_API_KEY"Supabase Storage
Enterprise
Reflexio Enterprise uses Supabase for storage with automatic provisioning and managed infrastructure. Hosted accounts are configured with managed storage when you create an account. You can switch to your own Supabase project from Settings; self-hosted Enterprise deployments can configure Supabase as shown below.
For production deployments that need managed cloud storage, you can configure Supabase manually:
from reflexio.models.config_schema import StorageConfigSupabase
storage = StorageConfigSupabase(
url="https://your-project.supabase.co",
key="your_service_role_key",
db_url="postgresql://...",
# Optional: route search reads through a read-only PostgREST endpoint
read_url="https://your-reader.supabase.co",
read_key="your_reader_key",
)
config.storage_config = storage
client.set_config(config)curl -X POST "${REFLEXIO_URL:-https://www.reflexio.ai}/api/set_config" \
-H "User-Agent: my-agent-reflexio" \
-H "Authorization: Bearer $REFLEXIO_API_KEY" \
-H "Content-Type: application/json" \
--data @- <<'JSON'
{
"...": "updated full config object"
}
JSON| Field | Type | Description |
|---|---|---|
url | str | Supabase project URL |
key | str | Supabase service-role key (needs write access) |
db_url | str | PostgreSQL connection string |
read_url | str | Optional. Supabase reader URL for search. Defaults to url. |
read_key | str | Optional. Reader key for search. Defaults to key. |
schema | str | Optional. Used by hosted Reflexio for platform-managed per-org schemas. Omit this for bring-your-own Supabase storage. |
Search uses reader credentials when provided, so search results can be bounded-stale on replicated infrastructure. Mutations and publish/generation consistency reads continue to use the writer credentials.
PostgreSQL Storage
Enterprise
Reflexio Enterprise can also store data in a customer-owned PostgreSQL database, such as AWS RDS, without running Supabase or PostgREST. Auth/login storage remains separate from data storage.
from reflexio.models.config_schema import StorageConfigPostgres
storage = StorageConfigPostgres(
db_url="postgresql://user:password@host:5432/database",
schema="public",
# Optional reader pool for search traffic
read_db_url="postgresql://user:password@reader:5432/database",
read_pool_size=10,
)
config.storage_config = storage
client.set_config(config)curl -X POST "${REFLEXIO_URL:-https://www.reflexio.ai}/api/set_config" \
-H "User-Agent: my-agent-reflexio" \
-H "Authorization: Bearer $REFLEXIO_API_KEY" \
-H "Content-Type: application/json" \
--data @- <<'JSON'
{
"...": "updated full config object"
}
JSON| Field | Type | Description |
|---|---|---|
db_url | str | PostgreSQL connection string |
schema | str | Optional. Target schema for Reflexio data. Defaults to public. |
pool_size | int | Optional. Maximum direct SQL connections per process (per organization). Defaults to 10. |
pool_acquire_timeout | float | Optional. Seconds a query waits for a free pooled connection before failing. Defaults to 30.0. |
read_db_url | str | Optional. Reader PostgreSQL connection string for search. Defaults to db_url. |
read_pool_size | int | Optional. Maximum reader connections per process. Defaults to pool_size. |
read_pool_acquire_timeout | float | Optional. Seconds search waits for a free reader connection. Defaults to pool_acquire_timeout. |
PostgreSQL storage requires PostgreSQL 14+ with pgvector available.
The pool is shared by all concurrent work for an organization. When in-flight
queries exceed pool_size, additional queries queue for up to
pool_acquire_timeout seconds rather than failing immediately; only a query that
waits longer than the timeout raises an error. Because pool_size is per
organization, the total server-side connection count scales with the number of
active organizations — size it against your database's max_connections.
In self-host deployments, pool settings can be set without editing config via
REFLEXIO_POSTGRES_POOL_SIZE, REFLEXIO_POSTGRES_POOL_ACQUIRE_TIMEOUT,
REFLEXIO_POSTGRES_READ_DB_URL, REFLEXIO_POSTGRES_READ_POOL_SIZE, and
REFLEXIO_POSTGRES_READ_POOL_ACQUIRE_TIMEOUT.
Search/read timeout knobs are also available for production deployments:
REFLEXIO_SUPABASE_HTTP_TIMEOUT_SECONDS for Supabase/PostgREST and
REFLEXIO_POSTGRES_STATEMENT_TIMEOUT_MS for native Postgres.
Row Retention
Reflexio applies high-water row limits to data tables on the publish path. When
an eligible table reaches its limit, the server deletes the oldest 20% of rows
for that table by created_at.
# Defaults to 250000 rows per target
REFLEXIO_ROW_LIMIT_INTERACTIONS=500000
REFLEXIO_ROW_LIMIT_PROFILES=250000
# Set a target to 0 to disable its cleanup
REFLEXIO_ROW_LIMIT_PLAYBOOK_OPTIMIZATION_EVENTS=0The legacy INTERACTION_CLEANUP_THRESHOLD variable still applies to
interactions when REFLEXIO_ROW_LIMIT_INTERACTIONS is unset.
Enterprise Self-Host Single Database
Enterprise
Enterprise self-host deployments can run with one customer-owned database for both login metadata and Reflexio data. Set DEPLOYMENT_MODE=self_host, choose REFLEXIO_STORAGE=supabase or REFLEXIO_STORAGE=postgres, and provide SELF_HOST_USERNAME / SELF_HOST_PASSWORD for the only login account.
For Supabase self-host, configure DATA_SUPABASE_URL, DATA_SUPABASE_KEY, and DATA_DB_URL. For vanilla Postgres self-host, configure DATA_DB_URL. Startup applies auth and data migrations to that same database and stores the generated configuration_json in public.organizations.
Usage-metering WAL volume (self-host)
Enterprise
Self-host meters usage to a small encrypted write-ahead log (WAL) on disk, not to your database. Mount a persistent, writable volume at REFLEXIO_USAGE_WAL_PATH (default ~/.reflexio/usage_wal) — this is required for restart-safe metering. Boot fails if the directory is not writable. In single-instance mode, an ephemeral or default path logs a warning because usage counters reset on restart. In multi-instance mode (REFLEXIO_BYOC_MULTI_INSTANCE=true), an ephemeral or default path is a startup failure because each replica must keep its own durable WAL state.
In multi-instance deployments, give each replica its own persistent WAL
directory. Reflexio generates a stable instance id and persists it at
REFLEXIO_USAGE_WAL_PATH/instance_id; that file is the preferred identity for
usage shipping and replay protection. Set REFLEXIO_INSTANCE_ID only when your
orchestrator guarantees uniqueness, such as a Kubernetes StatefulSet ordinal
combined with a per-replica PVC. In Kubernetes, either use that ordinal+PVC
pattern or let Reflexio keep its generated id on each replica's PVC. If the WAL
files become unreadable, startup fails closed and you must recover from the
original preserved files rather than starting from an empty directory.
Activating a Self-Host Data Plane
Enterprise
When Reflexio provisions your self-host account, the admin console's Onboard self-host customer flow shows a one-time activation key. Configure your data plane with that key — the control-plane URL defaults to Reflexio cloud.
# The activation key shown once in the Reflexio admin portal.
BYOC_DEPLOYMENT_SECRET="rflx-dep-…"
# Optional — the Reflexio control-plane base URL. Defaults to the Reflexio cloud
# control plane (https://www.reflexio.ai); set it only to target a different one.
# CONTROL_PLANE_INGEST_URL="https://www.reflexio.ai"On startup the data plane calls POST /api/billing/byoc/activate, which confirms
the key→deployment binding and returns your deployment id, org id, the
central public key, and capability fields for usage-protocol negotiation. In
multi-instance mode the control plane can raise usage_protocol_min and set
multi_instance_v2_only=true to require the v2 usage-reporting protocol; the
data plane should treat those fields as the contract for which usage protocol
it is allowed to speak after activation. Your data plane then ships usage and
pulls its entitlement lease automatically — you do not need to set
BYOC_DEPLOYMENT_ID or CONTROL_PLANE_PUBLIC_KEY (the activation handshake
supplies them).
The activation key is your deployment's credential: keep it secret, and rotate it from the admin portal if exposed.