Production Checklist
Production-readiness concerns are spread across many pages. This page collects them into one ordered checklist: each item states what to set, why, and the config key or API, then links to the page that documents it in depth. All defaults and failure modes below reflect v0.37.0.
Security
- Set
vef.security.secret. When unset, the framework generates an ephemeral per-process JWT signing key and logs a warning: tokens do not survive a restart and do not work across nodes. Generate a stable value withsecurity.GenerateSecret()and provision it per deployment; startup also warns when the value is the publicsecurity.DefaultJWTSecret. See Authentication Reference. - Set
vef.app.trusted_proxiesbehind a reverse proxy. With the list empty,X-Forwarded-Foris ignored and the client IP is the direct connection peer — behind a load balancer every request then shares the proxy's IP for rate-limit keys and IP whitelists. List only proxy IPs or CIDR ranges you control. See Configuration Reference. - Enable CORS deliberately. The CORS middleware is registered but inert
until
vef.cors.enabled = true; browser clients then need an explicitallow_originslist. See Configuration Reference. - Review the auth endpoint rate limits.
vef.security.login_rate_limitdefaults to6andrefresh_rate_limitto1(per key, 5-minute sliding window). Limiter state is in-memory per instance, so a multi-node deployment multiplies the effective limit by the node count. See Built-in Resources. - Keep
vef.mcp.require_authon. The MCP endpoint requires Bearer auth when the key is unset ortrue; only an explicitfalseallows anonymous access. See MCP. - Use a Redis nonce store for signature auth on multiple nodes. Signature
authentication defaults to an in-memory nonce store, so replay protection
is per process; supply
security.NewRedisNonceStorefor distributed deployments. See Authentication. - Size
vef.app.body_limit. The request body limit defaults to32mib; lower it when you do not accept large payloads, raise it deliberately when you do. See Configuration Reference.
Data
- Turn on database TLS.
ssl_modedefaults todisable; setrequire,verify-ca, orverify-full(plusssl_root_certfor a private CA) on every network data source. See Data Sources. - Consider
enable_sql_guard = true. Off by default. When enabled, dangerous raw-SQL statements (DROP,TRUNCATE,DELETE/UPDATEwithoutWHERE) are blocked unless the query context is whitelisted. See Data Sources. - Decide on Redis.
vef.redis.enableddefaults tofalse, which injects a nil client. What depends on Redis: theredis_streamevent transport (its constructor returns nil when the client is nil, so enabling the transport without enabling Redis silently leaves its routes unserved),cache.NewRediscaches (panic on a nil client), and the Redis nonce store from item 6. Challenge tokens are JWT-based and per-operation rate limits are in-memory, so neither needs Redis. See Configuration Reference.
Storage
- Set a real storage provider. With
vef.storage.providerunset, the framework falls back to in-memory storage and logs a warning — objects are lost on restart. Usefilesystemorminiofor any non-test deployment. See Storage. - Register a
FileACLbefore storing private files. The default ACL grants reads only underpub/and denies every other key regardless of who asks; override it viavef.SupplyFileACL(...)once you servepriv/*files. See Storage. - Route storage events through the outbox. The storage module fails fast
at startup unless
vef.storage.*events resolve to a transactional transport: enablevef.event.transports.outboxand add a routing rule, or makeoutboxthe default transport. See Storage.
Events
- Pick a production transport. The default
memorytransport is neither durable nor transactional: events are lost on crash or restart, and the default queue-full policy fails the publish withevent.ErrQueueFull. For anything that must survive the process, useoutbox(transactional, durable, at-least-once, publish-only, relays into a sink) and/orredis_stream(durable, at-least-once, cross-process). See Event Bus. - Plan for at-least-once semantics. Durable transports may deliver
duplicates: subscribe with
event.WithGroup(...)(required on at-least-once routes) and keep the Inbox middleware enabled for dedupe. See Event Bus.
Operations
- Verify shutdown grace periods.
vef.Runstops through the FX lifecycle on SIGINT/SIGTERM: the HTTP server gets a 30-second grace period for in-flight requests and the overall stop timeout is 60 seconds. Give your orchestrator at least that much termination grace. See Lifecycle. - Decide who may call
sys/monitor. Monitoring endpoints require Bearer auth by default (any authenticated principal, per-action rate-limit max60); add permission checks or network controls if host metrics are sensitive in your environment. See Monitor and Built-in Resources. - Set the log level.
VEF_LOG_LEVELacceptsdebug|info|warn|errorand defaults toinfo. See logx. - Inject build info. Generate build metadata with
vef-cli generate-build-infoand supply it viavef.Supply(BuildInfo); without it,sys/monitorreportsunknownfor app version, build time, and git commit. See CLI Tools and Monitor.
Next step
Read the Configuration Reference for
every key mentioned here, or Lifecycle for what
actually happens between vef.Run(...) and the first request.