SuperAPI AI Directory

rust-axum-production

Coding & development

View repository

Updated 10-15 20:32

About this skill

Rust Axum in production

A production-ready Axum service is predictable under failure, observable, and secure by default. Apply together with axum and, in the general go-live, production-readiness. Logs/spans: tracing. Runtime: tokio. Client: reqwest.

Boot and configuration

  • Load config from env (and files if the project uses them) once at startup.
  • Validate with types (figment, config, envy, or manual parse) — fail fast if a secret/DB URL is missing.
  • Separate development / staging / production (logs, auto-migrate, error verbosity).
  • Do not read env inside handlers.
APP_ENV=production
DATABASE_URL=...
RUST_LOG=info,tower_http=info,my_app=info
LISTEN_ADDR=0.0.0.0:8080

Process and shutdown

  • Explicit bind (0.0.0.0 in container; localhost only in dev if desired).
  • Graceful shutdown on SIGTERM/SIGINT: stop accepting connections, drain requests, close pool.
  • Defined shutdown timeout (e.g., 30s); log what did not drain.
  • tokio::spawn of background tasks with cancellation on shutdown (CancellationToken / watch / AbortHandle).

Health and readiness

Endpoint Meaning
/health or /live Process up
/ready Critical dependencies ok (DB ping)
  • Liveness must not fail just because the DB is slow (avoids kill loop), unless the orchestrator policy says otherwise.
  • Readiness fails if it cannot serve traffic.
  • Does not require auth; does not leak internals.

Timeouts, limits, and resilience

  • TimeoutLayer global or per route group.
  • Body limit (DefaultBodyLimit / RequestBodyLimitLayer).
  • Timeouts on all external HTTP/DB clients.
  • Retries only on idempotent transient errors, with backoff and jitter.
  • Circuit breaker / degradation when the domain requires it.
  • DB pool: max_connections aligned with CPU/latency; do not blindly copy defaults in multi-replica.

Observability

  • tracing + tracing-subscriber (JSON in production) — details in the skill tracing.
  • TraceLayer of tower-http with request id / correlation id.
  • Propagate traceparent / request id if the ecosystem uses it.
  • Metrics: latency, error rate, saturation (Prometheus via metrics or the project's standard).
  • Spans in relevant handlers/services — without logging body with PII/secrets.
  • 5xx errors: log with cause; external response generic.

Security

  • TLS at the edge (proxy) or in the process if that is the deploy standard.
  • Explicit CORS: origins allowlist; never * with credentials.
  • Headers: Strict-Transport-Security, X-Content-Type-Options, frame policy according to the app.
  • Cookies: HttpOnly, Secure, SameSite appropriate.
  • Auth: JWT/session validated in extractor; authz per resource.
  • Secrets only in env/secret manager; cargo audit / SCA in CI.
  • Rate limit on login and expensive endpoints (middleware or API gateway).

HTTP and contracts

  • Stable error JSON: { "code", "message", "request_id"? }.
  • Correct status codes; do not mask 500 as 200.
  • Pagination with a cap; reject limit abusive.
  • Uploads: type/size validated; store outside ephemeral disk without a plan.

Database and migrations

  • Migrations in the pipeline before releasing traffic (job or controlled init).
  • Avoid migrate on boot in multi-replica without lock/leadership.
  • Runtime connections + statement timeouts when the driver allows it.
  • Documented rollback/forward strategy for destructive changes.

Container and deploy

  • Docker multi-stage: build cargo build --release, distroless/slim runtime with certs.
  • Non-root user; static binary or minimal deps.
  • WORKDIR, EXPOSE, STOPSIGNAL SIGTERM.
  • Orchestrator healthcheck pointing to /ready or /health.
  • Resources: CPU/memory requests/limits; graceful period > shutdown timeout.
  • Build: Cargo registry cache in CI; Cargo.lock committed in bins.

Production performance

  • Release builds (--release); LTO/codegen only with evidence.
  • Avoid unnecessary hot allocations; measure with profiling under load.
  • HTTP compression if CPU is to spare and the payload is large.
  • Keep-alive connections behind the proxy; HTTP/2 when the edge supports it.

Go-live checklist

  • Typed config; boot fails if invalid
  • Graceful shutdown tested (SIGTERM)
  • /health and /ready correct
  • Timeouts + body limits active
  • JSON tracing + request id
  • Basic metrics/alerts
  • CORS/headers/authz reviewed
  • Migrations in the pipeline
  • Non-root image; cargo audit clean enough
  • Post-deploy smoke test and rollback plan

Anti-patterns

  • RUST_LOG=debug in production with PII
  • Uncaught panics bringing down the process during request handling (prefer Result)
  • A single instance with in-memory state without sticky/session store
  • Opening CORS to the world to “test quickly” and forgetting
  • Deploy without readiness (traffic to an app still migrating)

Completion criteria

  • Service starts, serves health/ready and shuts down cleanly with SIGTERM
  • Dependency failures appear in logs/metrics, not as silence
  • Hardened HTTP surface (limits, timeouts, CORS, authz)
  • Defined migrate + deploy + smoke pipeline
  • No secrets in the artifact or logs