Go-live checklist
Each item states what must be true before production and links to the page that explains it. examples/53-production-sql wires most of them in one program.
Keys
- Signing keys and cookie keys are loaded from persistent storage with
op.LoadKeysetandop.LoadSymmetricKeys, so every replica publishes the samekidand a restart does not log users out. See Key rotation. - A rotation plan exists: the retiring signing key and the retiring cookie key stay listed until the tokens and sessions they protected have expired. See Key rotation.
Storage
- The schema is applied once per release from a deploy job, either by your migration tool from
Store.Migrations()or byStore.Migrate(ctx), not from every replica's startup. See Storage maintenance. - On MySQL, the indexes and the binary collations of an existing database come from the files in
Store.Migrations(), whichStore.Migrateor your tool applies. The schema check reports a missing index and a non-binary collation. See Persistent storage (SQL). op.Newchecks at startup the schema of the tables the configuration uses, so a missing table or column stops the start-up instead of failing a later request;Store.ValidateSchemavalidates all tables in a deploy gate. See Persistent storage (SQL).- A retention sweep (
Store.GCorRunGC) is scheduled on one replica. One is enough, and sweeps that overlap on several replicas are safe, so no leader election is needed. Nothing else deletes expired rows, so the tables grow without bound until it runs. See Storage maintenance. - Backups and recovery targets are set for each substore. See Backup & disaster recovery.
Network and clients
op.WithTrustedProxieslists the CIDRs of the reverse proxy or ingress, so the OP sees the real client address and scheme. Without it theX-Forwarded-*headers are ignored. See Mount on your router.- Static clients are synchronised with
op.SyncStaticClientsfrom a deploy job before the new version starts. A changed definition is refused at startup until then. See Client onboarding. - The security profile is chosen on purpose, and the
startup.profileaudit event shows the posture you deployed. Withoutop.WithProfilePKCE is required of every client; a relying party that cannot send it is admitted only by declaringprofile.OIDCCore. See Declaring a security profile. - Every static confidential client has a plaintext
Secretof at least 32 bytes (mint one withop.NewClientSecret) or aSecretHash;op.Newrefuses a shorterSecret. See Client onboarding. - Clients that send DPoP proofs sign the endpoint URL the OP advertises in discovery, not an internal address behind the proxy; any other URL is refused whatever the profile.
Running it
- No
op.WithAllowInsecureOutboundForDevorop.WithAllowLocalhostIssuerForDevis in the production option list; both exist for a development issuer, andop.Newrefuses the former against any other. op.WithLoggeris set. Without it, construction warnings and the line that names optional store capabilities a custom store lacks go toslog.Default(), and every request-time record is discarded. See Observability.- The container memory limit allows
GOMAXPROCS × 64 MiBfor hashing. Each password check and eachclient_secretcheck runs Argon2id at 64 MiB and about 90 ms, and checks run concurrently up toGOMAXPROCS. A high-rate machine-to-machine client avoids the cost withop.WithHighEntropyClientSecrets. See Service-to-service (client_credentials). - Replicas share the session, grant and replay-set stores. With DPoP server nonces enabled they also share one
op.DPoPNonceSource, and a login flow with a password or second-factor step has a durable, shared lockout store. See Multi-instance deployment. - Shutdown stops the HTTP server first and then calls
Provider.Shutdown, so queued back-channel logout deliveries finish. See Multi-instance deployment. - If the handler is built with
op.NewReloadable, a key or option change is applied withReload, and the same option list is used at startup and on every reload. See Key rotation.