Skip to content

Configuration Reference

The engine is configured with environment variables. This page lists the engine's variables, grouped by what you are setting up, with the default the engine applies. Each feature page lists the settings of its own feature, and Feature settings says where each one is.

Seven variables decide whether the engine starts. Set these first.

VariableWhat it doesDefault
DATABASE_URLConnection string. The scheme picks the database: postgres:// or postgresql://, mysql://, or sqlserver://. See supported databases.required
JWT_SECRETFallback token signing secret, at least 16 characters. Sessions are signed with an Ed25519 key the engine creates at JWT_KEY_PATH, but the engine refuses to start without this value.required
ENCRYPTION_KEYEncrypts stored credentials with AES-256-GCM. At least 32 characters and different from JWT_SECRET. A new value makes the stored credentials unreadable, so generate it once.required
APP_ENVproduction or development. Production refuses a weak configuration, as listed below.production
LYEVE_AUDIT_HMAC_KEYKey for the audit log's tamper-evident chain. Exactly 64 hex characters.required in production
RATE_LIMIT_RPSRequests per second per client address for the global limiter. Unset or 0 turns the limiter off, which production refuses.unset
SECURE_COOKIEtrue marks cookies Secure, sends HSTS and redirects plain HTTP to HTTPS. Production refuses any other value.false

A minimal production environment, with each secret generated separately:

Terminal window
DATABASE_URL="postgres://lyeve:<password>@db.example.com:5432/lyeve?sslmode=require"
JWT_SECRET="$(openssl rand -hex 32)"
ENCRYPTION_KEY="$(openssl rand -hex 32)"
LYEVE_AUDIT_HMAC_KEY="$(openssl rand -hex 32)"
RATE_LIMIT_RPS=100
SECURE_COOKIE=true
LYEVE_CONSOLE_URL="https://admin.example.com"

For a local try, set APP_ENV=development and the production checks are skipped. A stateless engine needs neither DATABASE_URL, JWT_SECRET nor ENCRYPTION_KEY.

With APP_ENV unset or production, the engine does not start when:

  • SECURE_COOKIE is not true.
  • RATE_LIMIT_RPS is unset or 0.
  • LYEVE_AUDIT_HMAC_KEY is unset or is not exactly 64 characters.
  • JWT_EXPIRY_SECS is above 3600.
  • DATABASE_URL or DATABASE_REPLICA_URL signs in as the database's default superuser: postgres on PostgreSQL, root on MySQL, sa on SQL Server.
  • The signing key file at JWT_KEY_PATH is readable by group or others, or cannot be created.
  • LYEVE_CONSOLE_URL is set and does not start with https://.

In every environment, the engine does not start when:

  • ENCRYPTION_KEY is unset. The engine then uses JWT_SECRET in its place, and the two may not be equal.
  • JWT_SECRET is shorter than 16 characters, or ENCRYPTION_KEY shorter than 32, or the two are equal.
  • Either secret is a placeholder: secret, password or default, or a value containing changeme, change-me, change-this, replace-me, replaceme, your-secret, dev-secret, insecure, example or placeholder.
  • CORS_ORIGINS contains *.
  • JWT_ALG, PASSWORD_HASH_ALGO, STORAGE_DRIVER or DATABASE_DRIVER names a value the engine does not support.
  • One of the engine's numbers or durations does not parse. A few, such as the POOL_* and HEALTH_* values, fall back to their default instead.

A production engine starts but logs a warning on every boot when LYEVE_CONSOLE_URL is unset, and when a PostgreSQL DATABASE_URL sets no sslmode or one other than require, verify-ca or verify-full.

The engine reads each setting from four places. The highest one that has it wins:

  1. An environment variable. A variable set to an empty value turns the setting off, and no lower layer fills it back in.
  2. The YAML file, lyeve.yaml. It wins over the admin console unless the value is tagged !overridable.
  3. The admin console, which holds what a feature's configuration form saved.
  4. The built-in default.

The engine reads the variables in the engine tables on this page once, at startup, before it connects to the database. Set them in the environment or the file, and restart to change them. A feature's settings, such as the mail relay or the idempotency TTLs, can also be saved in the console. A setting the feature reads each time it uses it applies at once. One it reads only when it starts applies at the next restart. Three are kept until a restart on purpose, because changing them under a running server breaks something that cannot be undone:

  • the WebAuthn relying party (every registered passkey stops working)
  • the encryption key (stored credentials become unreadable)
  • the idempotency keyspace and backend (a retry stops finding its record, so the request runs twice)

GET /api/admin/config (super admin) lists every setting that the environment, the file or the console sets, with the layer it came from and, for an engine setting, what it does and its default. Secrets show no value. PUT /api/admin/config (super admin) saves into the console layer and refuses a key a higher layer holds:

Terminal window
curl -X PUT https://admin.example.com/api/admin/config \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"values": {"flow_run_retention": "168h"}}'

The answer lists what it stored under saved, each with the layer it now resolves from, and what it refused under refused, each with the reason and, for a file value, the file and line. When nothing could be saved it answers 409. The quickstart shows how to get TOKEN.

Every variable that is not marked "environment only" below has a place in lyeve.yaml. A nested key is the variable name with the path joined by underscores, so storage.s3.bucket is STORAGE_S3_BUCKET:

database:
url: ${DATABASE_URL}
max_connections: 25
storage:
driver: s3
s3:
bucket: media
region: eu-west-1

Flat names work too, so an existing .env file can be copied in a line at a time. ${VAR} and ${VAR:-fallback} read the process environment, which is how a container passes a secret in without it living in a committed file.

The engine looks for lyeve.yaml or lyeve.yml in the working directory, then in /etc/lyeve/, then for a /etc/lyeve/conf.d/ directory. LYEVE_CONFIG points at a specific file or directory instead. A named path that does not exist stops the boot.

Feature settings go under a plugins block, which drops its own segment, because a feature's key already names it. plugins.cache.driver is CACHE_DRIVER:

plugins:
cache:
driver: !overridable redis
ttl: "60s"

!overridable lets the admin console take a key over. Without it the file value is final, and the console shows the field read-only, naming the file and line it came from. LYEVE_OVERRIDABLE does the same for environment variables: a comma-separated list of keys the console may take over. A listed key keeps its variable's value until something is saved against it. It is read once at startup.

$include:
- base.yaml
- environments/staging.yaml
- schemas/*.yaml

Included files merge first, so the including file overrides them. A conf.d/ directory beside the named file merges last, which lets a deployment extend a packaged base without editing it. A directory of files merges in lexical order, so 10-base.yaml then 20-staging.yaml layers the way it reads. Content types can be declared in these files too. See Moving content types between projects.

A credential saved on a feature's configuration form is encrypted at rest with a key derived from ENCRYPTION_KEY and is never returned. A set credential reads as ********. Writing that value back leaves the stored one alone, so editing one field of a form does not overwrite the rest. Submitting an empty value clears it.

VariableWhat it doesDefault
DATABASE_URLSee Start here.required
DATABASE_MAX_CONNECTIONSMost connections the engine opens to the database. Multiply by the number of replicas and stay under the database's own limit.25
DATABASE_REPLICA_URLA read replica. Read-heavy queries that tolerate lag go to it. Production refuses a default superuser here too.unset (all reads go to the primary)
DATABASE_REPLICA_MAX_CONNSMost connections to the replica.30
Pool tuning and an external pooler
VariableWhat it doesDefault
DB_POOL_MIN_CONNSConnections opened at startup, so the first requests do not wait for a handshake.2
DB_CONN_MAX_LIFETIMEHow long a connection is used before it is replaced, as a duration.1h
DB_POOL_HEALTH_CHECK_PERIODHow long an idle connection stays open before it is closed. Above zero, it replaces DB_CONN_MAX_IDLE_TIME.30s
DB_CONN_MAX_IDLE_TIMEThe idle timeout used when DB_POOL_HEALTH_CHECK_PERIOD is 0.5m
MIGRATIONS_PATHDirectory of the database migrations the engine applies at startup. The image sets it../migrations (/app/migrations in the image)
DATABASE_DRIVEROverrides the database type read from DATABASE_URL: postgres, mysql or mssql. Leave it unset.read from the URL
CONNECTION_POOLERpgbouncer or proxysql when an external pooler sits in front of the database, so the pool health report at GET /api/admin/pool/health includes its sizing. The engine does not configure the pooler.none
POOL_MAX_CLIENT_CONNThe pooler's client connection limit, for that report. Environment only.100
POOL_DEFAULT_POOL_SIZEThe pooler's default pool size, for that report. Environment only.20
POOL_RESERVE_POOL_SIZEThe pooler's reserve pool size, for that report. Environment only.5
POOL_TENANT_SIZESPer-tenant pool sizes as a JSON array of {"slug", "pool_size", "min_pool_size", "max_connections", "db_name"}. Invalid JSON is logged and ignored. Environment only.unset
POOL_HEALTH_MAX_LATENCYPing latency above which the pool health report says degraded. Environment only.1s
POOL_HEALTH_MIN_IDLEIdle connections below which the report says degraded. Environment only.1
POOL_HEALTH_MAX_UTILShare of the pool in use above which the report says degraded. Environment only.0.9

The CONNECTION_POOLER and POOL_* sizing variables are read only when CONNECTION_POOLER names a pooler. The POOL_HEALTH_* thresholds are read on every install.

VariableWhat it doesDefault
LYEVE_CONSOLE_URLThe admin console's public URL, such as https://admin.example.com. Password reset and magic-link emails link to pages the console serves, and device sign-in shows its approval page there. It must be an absolute URL with no query or fragment. In production it must be https, and while it is unset password reset and magic-link sign-in refuse to start and device sign-in answers 503.http://localhost:5173 outside production
LYEVE_BASE_URLThe public base URL of the engine. Features that build an absolute link to it use this value instead of the request's Host header: OAuth and SAML callback URLs, data export downloads and file links. Set it in production.unset
TRUSTED_PROXIESComma-separated CIDRs of the reverse proxies in front. X-Forwarded-For is honored only from these, so rate limits and audit entries see the real client address. Unset, every request counts as the proxy's.unset
CORS_ORIGINSComma-separated origins of the browser apps that call the APIs cross-origin. * is refused.http://localhost:5173
ADMIN_LISTEN_ADDRBind address of the Admin API.0.0.0.0:3001
API_LISTEN_ADDRBind address of the Content API.0.0.0.0:3002
TLS_CERT_FILE, TLS_KEY_FILEA PEM certificate and key, set together. Both listeners then serve TLS 1.2 or later and pick up a rotated certificate without a restart. Unset, both serve plain HTTP for a proxy that terminates TLS.unset
Host and address filters, CORS details
VariableWhat it doesDefault
ALLOWED_HOSTSComma-separated host names the engine answers to. Any other Host header gets 421.unset (every host)
IP_ALLOWLISTComma-separated CIDRs or addresses allowed to connect. Others get 403. An entry that does not parse stops the boot.unset (every address)
CORS_ALLOWED_DOMAINSComma-separated domain suffixes under which a tenant's own domain may call the APIs cross-origin, such as example.com for shop.example.com. Empty allows no tenant domain.unset
CORS_ALLOW_METHODSMethods the preflight allows.GET, POST, PUT, DELETE, PATCH, OPTIONS
CORS_ALLOW_HEADERSRequest headers a browser may send. It replaces the default list, so keep Authorization and X-Tenant-ID if you set it.Content-Type, Authorization, X-API-Key, X-Tenant-ID, X-Correlation-ID, X-CSRF-Token
CORS_EXPOSE_HEADERSResponse headers a cross-origin script may read. The default lets a browser client read the request id and the rate-limit values.X-Request-Id, X-Correlation-ID, RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After
CORS_MAX_AGESeconds a browser may cache the preflight.3600
VariableWhat it doesDefault
JWT_KEY_PATHWhere the Ed25519 signing key is kept. Put it on a volume, or give every replica the same file, or each restart signs everyone out. In production the file must be readable by its owner only./var/lib/lyeve/jwt_key.json
JWT_EXPIRY_SECSSession token lifetime in seconds. Production refuses a value above 3600.900 (15 minutes)
REFRESH_TOKEN_TTL_SECSRefresh token lifetime in seconds.2592000 (30 days)
LYEVE_SETUP_TOKENThe token the first-run setup asks for, at least 16 characters. Unset, the engine prints a one-time token to its log while no account exists. Set it when more than one replica can answer setup, since each prints its own.unset (a logged one-time token)
ADMIN_CONSOLE_KEYA secret of at least 32 characters, shared with the admin console. The console signs its calls with the browser's address, so sign-in limits count each person instead of the console server.unset
PASSWORD_MIN_LENGTHShortest password accepted.12
Signing, rotation, password rules and setup mode
VariableWhat it doesDefault
JWT_ALGEdDSA signs sessions with the Ed25519 key. HS256 signs them with JWT_SECRET and creates no key file. Any other value stops the boot. Environment only: a value in the file passes the check but does not change the signing.EdDSA
JWT_SECRETSComma-separated HS256 secrets that verify tokens during a rotation. JWT_SECRET still signs, so list its value first and the old secret after it. Unset, JWT_SECRET alone verifies.unset
ADMIN_CONSOLE_KEY_PREVIOUSThe old console key, still accepted while you rotate. Set the new key in ADMIN_CONSOLE_KEY, move the console to it, then unset this one. Needs ADMIN_CONSOLE_KEY, at least 32 characters.unset
PASSWORD_HASH_ALGObcrypt or argon2id.bcrypt
PASSWORD_REQUIRE_COMPLEXITYRequires an upper-case letter, a lower-case letter and a digit.true
PASSWORD_CHECK_COMMONRefuses passwords on a list of common ones.true
TRUSTED_ISSUERSComma-separated base URLs of outside OpenID Connect issuers whose tokens the Content API accepts. Keys are fetched from {issuer}/.well-known/jwks.json. See Scaling.unset
TRUSTED_ISSUER_POLICIESA JSON array giving each trusted issuer its tenant and the roles its users map to. An issuer with no policy has its tokens ignored, and a policy for an unlisted issuer stops the boot.unset
API_KEY_PEPPERA server secret mixed into every stored API key hash. See API keys.unset
ENFORCE_API_KEY_PEPPERtrue stops the boot when no API_KEY_PEPPER is found.false
LYEVE_SETUP_MODEtrue lets the engine start without DATABASE_URL, JWT_SECRET or ENCRYPTION_KEY. It then serves only the probes and the setup routes, and the admin console shows what to set. See Installation.unset
VariableWhat it doesDefault
RATE_LIMIT_RPSSee Start here.unset
RATE_LIMIT_BURSTRequests a client address may send at once above the steady rate.twice RATE_LIMIT_RPS, at least 1
MAX_BODY_BYTESLargest request body on any route, in bytes. Sized for uploads.10485760 (10 MiB)
MAX_JSON_BODY_BYTESLargest body on JSON routes. Only Content-Length is checked, so a chunked request without it meets MAX_BODY_BYTES instead.1048576 (1 MiB)
Per-tenant limits, public routes and load shedding
VariableWhat it doesDefault
RATE_LIMIT_PER_TENANTtrue counts the global limit per tenant and address instead of per address.false
PUBLIC_RATE_LIMITSPer-route caps for public routes, comma-separated METHOD:/pattern=rate:burst entries using the route pattern exactly as documented, such as POST:/api/v1/flows/hooks/{flow_id}=20:40. Entries merge over the built-in table, so a route you do not name keeps its own limit. A malformed entry stops the boot and names the entry.built-in table
PUBLIC_RATE_LIMIT_GLOBALCombined per-address cap across every public route, as rate:burst. Raise it where many callers share one address: a CDN, a proxy on loopback, a load generator.50:100
BACKPRESSURE_ENABLEDTurns load shedding on. See Scaling.false
BACKPRESSURE_MAX_INFLIGHTRequests in flight before the engine sheds load.200
BACKPRESSURE_TENANT_QUOTA_PCTShare of that budget one tenant may hold, above 0 and at most 1.0.4
BACKPRESSURE_POOL_PRESSURE_THRESHOLDShare of the database pool in use at which shedding begins, above 0 and at most 1.0.85

To share the per-address limit across replicas through Redis, set RATE_LIMIT_BACKEND=redis. That setting belongs to Rate limiting.

These settings drive the engine's own file store. The Object storage feature runs on every install by default and takes its place. While it runs, STORAGE_DRIVER changes nothing, and the STORAGE_S3_* values only create its first provider on a start that finds none.

VariableWhat it doesDefault
STORAGE_DRIVERWhere uploaded files go: local or s3.local
STORAGE_LOCAL_PATHDirectory for the local driver. Mount a volume here../uploads (/app/uploads in the image)
STORAGE_BASE_URLPublic base URL of files kept by the local driver.unset
S3-compatible bucket
VariableWhat it doesDefault
STORAGE_S3_BUCKETBucket name.unset
STORAGE_S3_REGIONBucket region.us-east-1
STORAGE_S3_ENDPOINTEndpoint of an S3-compatible service such as R2 or MinIO. Unset uses AWS.unset
STORAGE_S3_KEYAccess key id.unset
STORAGE_S3_SECRETSecret access key.unset
STORAGE_S3_CDN_BASE_URLPublic base URL that file links use, such as a CDN in front of the bucket.unset
STORAGE_S3_USE_SSLConnects to the endpoint over TLS.true
STORAGE_S3_FORCE_PATH_STYLEtrue addresses the bucket in the path, as MinIO needs.false
STORAGE_S3_MULTIPART_MBSize in MB above which an upload is sent in parts.5

Object storage covers buckets per provider and signed links.

The mail relay is read by the features that send mail: Email, Password reset and Magic link sign-in. It can also be saved on the email feature's configuration form, and a variable set in the deployment still wins.

VariableWhat it doesDefault
SMTP_HOSTSMTP server host name. Unset, no mail is sent.unset
SMTP_PORTSMTP server port.587
SMTP_USERSMTP user name.unset
SMTP_PASSSMTP password.unset
SMTP_FROMThe From address of outbound mail.unset
SMTP_TLSExactly true selects implicit TLS, usually on port 465. Any other value sends over STARTTLS. Read by the Email feature only.false
VariableWhat it doesDefault
CACHE_TTLHow long the Content API keeps an entry or a list in its memory cache, as a duration. The Caching feature uses it as its default TTL.60s
CACHE_MAX_ENTRIESMost entries in each of those memory caches.1000
CACHE_DRIVERThe Caching feature's backend: memory or redis. Set redis to share sessions and sign-in lockouts across replicas. The Content API caches stay in memory either way.memory
REDIS_URLThe Redis that caching, idempotency, shared rate limits, realtime and flows use, unless a feature names its own.redis://localhost:6379/0

Scaling lists what more than one replica needs from Redis.

An Idempotency-Key header on a write makes it safe to retry: the request runs once, and a retry with the same key gets the stored answer. Keys are kept per tenant and user. Included free. See Idempotent requests.

VariableWhat it doesDefault
REDIS_URLShares idempotency records between replicas, so a retry that lands on another replica still finds its record. A Redis on the local host that does not answer falls back to in-process records and logs why. A remote one that does not answer stops the feature from starting.redis://localhost:6379/0
IDEMPOTENCY_KEYSPACEPrefix on every stored key. Needs a restart to change, as does the backend. The settings below apply without one.idem
IDEMPOTENCY_LOCK_TTLHow long a request in flight holds its key. A handler that outlives its lock is logged.30s
IDEMPOTENCY_DATA_TTLHow long a finished answer is kept for replay.24h
IDEMPOTENCY_AUTO_GENERATEDerives a key from the tenant, user, method, path and body when a request has none.false
IDEMPOTENCY_AUTO_METHODSComma-separated methods that get a derived key.POST
VariableWhat it doesDefault
LYEVE_LICENSE_KEYA signed license token, verified offline, or a license key, which the engine exchanges once for a token. Free features run with or without it.unset (free features only)
LYEVE_PLUGINSComma-separated features to start. Empty starts every feature that is free or your license covers. See Licensing and tiers.empty
LYEVE_LICENSE_SERVER_URLWhere a license key is exchanged. https only. Never contacted when LYEVE_LICENSE_KEY holds a token.https://api.lyeve.com
LYEVE_LICENSE_CACHE_DIRWhere the verified token and the install id are cached./var/lib/lyeve
MULTI_TENANTtrue serves more than one tenant from one install. See Tenants.false
LYEVE_MODEstateless runs the engine with no database. Any other value stops the boot. See Stateless mode.unset
LYEVE_CONFIGPath of the YAML file or directory to read. Environment only.unset (the search above)
LYEVE_OVERRIDABLEComma-separated variables the admin console may take over. Environment only.unset

/healthz, /readyz and /startup answer on both listeners. See health endpoints for what each one checks.

VariableWhat it doesDefault
PRESTOP_DRAIN_SECSSeconds /readyz answers 503 before shutdown starts, so the load balancer stops sending traffic first.5
GRACEFUL_SHUTDOWN_SECSSeconds requests in flight get to finish.60
Readiness thresholds
VariableWhat it doesDefault
HEALTH_DISK_PATHDirectory whose free space /readyz checks. Environment only.STORAGE_LOCAL_PATH
HEALTH_DISK_MIN_MBFree space in MB below which /readyz answers 503. Environment only.100
HEALTH_REDIS_PROBE_REQUIREDtrue makes /readyz answer 503 when the Redis that holds sessions is unreachable. Unset, that outage is reported but the replica stays in service. Environment only.false
HEALTH_GOROUTINE_MAXGoroutine count above which /readyz reports a warning. It does not fail the check. Environment only.10000
POOL_EXHAUSTION_THRESHOLDShare of the database pool in use above which /readyz reports a warning. It does not fail the check. Environment only.0.8
VariableWhat it doesDefault
METRICS_TOKENBearer token for GET /api/admin/metrics, so a scraper needs no admin account. While it is set, any other bearer token on that route answers 401. Unset, the endpoint answers a super admin.unset
OTEL_EXPORTER_OTLP_ENDPOINTOpenTelemetry collector to send traces to. Unset, tracing is off.unset
INSTANCE_IDNames this replica in logs, traces and the replica list.host name and process id
Tracing, debug traces and compression
VariableWhat it doesDefault
OTEL_EXPORTER_OTLP_INSECUREtrue sends to the collector without TLS.false
TRACING_SAMPLING_RATEShare of traces kept, 0.0 to 1.0. A value outside that range stops the boot.1.0
TRACING_TENANT_SAMPLING_RATESPer-tenant rates as comma-separated tenant=rate pairs. A malformed pair stops the boot.unset
LYEVE_DEBUG_TRACER_ENABLEDtrue lets an admin send X-Debug: true and get a trace of the request instead of the normal answer.false
COMPRESS_GZIP_JSON_LEVELgzip level for JSON responses. Environment only.4
COMPRESS_BROTLI_JSON_LEVELBrotli level for JSON responses. Environment only.2
COMPRESS_GZIP_TEXT_LEVELgzip level for text and HTML responses. Environment only.6
COMPRESS_BROTLI_TEXT_LEVELBrotli level for text and HTML responses. Environment only.4
VariableWhat it doesDefault
LYEVE_GDPR_HOLD_CHECKWhat an erasure request does when a legal-hold check is set up but cannot answer. refuse answers 503 and erases nothing. proceed erases anyway. Environment only.refuse
INSTANCE_REGIONThe data region this install serves. Answers carry it in X-CMS-Region, and Data residency compares a tenant's region against it.unset

An active legal hold stops POST /api/admin/gdpr/erase from erasing the person it covers. The request succeeds with total_rows: 0 and names the holds. Holds need the audit-retention feature. See Data protection.

The engine sizes itself to the container's memory and CPU limits, which it reads from the cgroup. GOMEMLIMIT and GOMAXPROCS, Go's own variables, win when you set them.

Memory, CPU and worker pools
VariableWhat it doesDefault
MEMORY_LIMIT_BYTESMemory limit used when the cgroup sets none. The engine sets Go's soft memory limit to 85% of the limit it finds.from the cgroup
CPU_QUOTAWhole cores the engine schedules for, instead of the cgroup's CPU limit.from the cgroup
GOROUTINE_ENGINE_ENABLEDWarms and stops features in parallel, applies GOROUTINE_ENGINE_POOL_SIZE and allows asynchronous hooks. The shared worker pool runs either way. See Concurrency tuning.false
GOROUTINE_ENGINE_POOL_SIZEWorkers in the shared pool. Applied only with GOROUTINE_ENGINE_ENABLED=true.100
DB_WARMUP_PARALLELISMHow many tasks the parallel stages, such as cache warmup, run at once.4
ASYNC_HOOKS_ENABLEDRuns after-save hooks in the background instead of inside the request. Needs GOROUTINE_ENGINE_ENABLED=true.false
ASYNC_HOOK_TIMEOUTHow long one asynchronous hook may run.5s
CONTROL_STRICT_MODEtrue stops the boot when a security control reports that it is not enforced. Unset, the engine logs the report and starts. Environment only.false

Each feature lists its own settings on its page. Find a variable here by its prefix.

You are setting upVariablesPage
Shared cachingCACHE_*, REDIS_URLCaching
Rate limits across replicasRATE_LIMIT_BACKEND, RATE_LIMIT_REDIS_URLRate limiting
Uploads and imagesMEDIA_*Media
Signed upload and download linksMAX_PRESIGN_*, STORAGE_LOCAL_SIGNING_SECRETObject storage
Keeping a tenant's files in its region without a data residency assignmentSTORAGE_TENANT_REGIONSObject storage
SearchSEARCH_*Search
Outbound mailSMTP_*Email
Magic linksMAGIC_LINK_*Magic link sign-in
Passkeys and one-time codesWEBAUTHN_*, MFA_TOTP_ISSUERMulti-factor authentication
Bot checksCAPTCHA_*Captcha
Device and IP reputationDEVICE_FINGERPRINT_CONFIG, IPREP_*Trusted devices
GraphQLGRAPHQL_*GraphQL API
gRPCGRPC_*gRPC API
RealtimeREALTIME_*Realtime
Message brokersEVENT_BUS, NATS_*, KAFKA_*, RABBITMQ_*Message broker events
Outbound webhooksWEBHOOK_ALLOWED_PRIVATE_NETWORKSWebhooks
FlowsFLOW_RUN_RETENTION, FLOW_CRON_ENABLEDFlows
Metrics exportMETRICS_* other than METRICS_TOKENMetrics export
Error alertsERROR_TRACKING_*, SLACK_WEBHOOK_URL, DISCORD_WEBHOOK_URLError tracking
AnalyticsANALYTICS_*Analytics
Uptime probesSYNTHETIC_MONITORING_*Synthetic monitoring
Request profilingPROFILER_*Request profiling
Slow queriesQUERY_MONITOR_*Slow query analysis
Data exportsDATA_EXPORT_*Data export
Tenant backups and keysKMS_*, STORAGE_S3_BACKUP_ALLOWED_BUCKETS, REPLICATION_TARGETSTenants
AIAI_*AI