Production checklist
The list to walk before flipping the DNS. Everything here matters at least a little; the bold items are the ones we’ve seen actually break a launch.
If you have read this page and verified each item, your Synq integration is production-ready by every standard Synq itself holds to. The reasoning behind each item is given in one line; the deep dive is linked.
Identity & sign-in
- OIDC client credentials are not committed to source.
SYNQ_CLIENT_SECRETlives in a secret manager (Vercel env, AWS Secrets Manager, Doppler, etc.), never.env.productionchecked into git. -
SESSION_SECRETis at least 32 characters. Generate withopenssl rand -base64 32. Rotate per Rotate everything. - Redirect URI is registered with the exact production host
including scheme.
https://app.example.com/api/auth/callback, nothttp://, not a wildcard, not the preview URL. - All BYO OAuth credentials are real production credentials. The dev / staging / prod Google project is not the same project. Google flags shared OAuth clients across environments and may throttle.
- Apple Sign-In’s
.p8key is uploaded to Synq. Apple invalidates the JWT-as-client-secret if the key file goes missing — sign-ins start failing silently 24 hours later. - Session cookie
Secureflag is on. Synq sets this by default; verify your reverse proxy isn’t stripping it.
Tokens & authorization
- Every backend that accepts a Synq access token verifies the
signature against the JWKS endpoint — not just the
iss/audclaims by themselves. Use the JWT claims reference to map every claim you care about. - JWKS cache TTL is no longer than 24 hours. Synq rotates signing keys; a stale cache will fail verification.
-
audis verified against the brand slug for access tokens and theclient_idfor ID tokens. The two audiences are deliberately different — don’t accept them interchangeably. -
requireAccess(predicate)is at every protected route. No route that returns user-specific data relies solely on the proxy-level cookie check. - Server Actions and Route Handlers each verify the session.
Per the
Next.js auth guide ,
proxy.tsis not your authorization boundary.
Webhooks
- Webhook endpoint is HTTPS only. Synq refuses to deliver to
http://in production. -
Synq-Signatureis verified with the per-endpoint secret on every delivery. UseverifyWebhookSignaturefrom@synqid/js— do not roll your own HMAC. - Endpoint returns 2xx within 10 seconds. If processing takes longer, enqueue and ack. Synq’s retry policy is exponential backoff with auto-disable after 10 consecutive non-2xx responses.
- Idempotency: deduplicate on the
Synq-Deliveryheader. Retries reuse the delivery ID so you can safely no-op duplicates. - Auto-disable alerting is wired up. If your endpoint gets auto-disabled, you need to know within minutes — not when a user reports they didn’t get their welcome email.
Operational
- At least two team members have access to the Synq dashboard. Single-bus-factor accounts have caused real outages. Add a backup admin.
- Rate-limit headroom is monitored. The
error reference lists the
headers; alert on
>80%usage so you have time to react. - Audit log is being consumed somewhere. A SIEM, a Slack channel, a quarterly review — pick one. The log existing isn’t the same as someone reading it.
- Custom domain has cert renewal alerting. Synq’s cert-manager is robust but the DNS pre-condition (CNAME) lives on your side and can drift.
- Secret rotation cadence is documented. Even if “rotate once a year” — write it down. See Rotate everything.
Resilience
- Sign-in failures degrade gracefully. If Synq’s
/userinforeturns 500, yourgetUser()returnsnulland the user sees a logged-out experience — not a 500 page. - Webhook ingest tolerates Synq being down. A failed Synq → webhook delivery should not surface as an error in your app. Synq’s retry covers it.
- Iron-session cookie size is under the 4 KB budget. If you add custom claims to the user object that get stuffed into the session cookie, watch the size. Browsers reject oversized cookies silently.
- The proxy matches
/api/authas public. If a misconfiguredmatcherexcludes it, sign-in deadlocks.
Compliance / privacy
- You have a DPA on file with Synq if your tenant requires one. Email legal@synq.id — turnaround is one business day.
- Personal data fields are minimized in your custom claims. The JWT is sent to your backend on every request; it’s logged by your edge / CDN / observability platform. Don’t put a passport number in there.
-
prefer_usernameandemailare scoped to the consent the user agreed to. Verify what the user consented to in Scopes and consent. - Account-delete webhooks are handled. When a user deletes
their Synq account, your
user.deletedhandler should delete or anonymize their data in your DB within 30 days.
Performance
-
verifySession()is called inside server components, not client components. Server primitives are cached per-render (React.cache()); client-side fetches are not. -
useUser()is seeded from a servergetUser()in the root layout. Don’t fetch the user from the client on first render. -
proxy.tsdoes not call any network endpoint. The proxy runs on every navigation and every prefetch — see the Next.js auth guide . Cookie presence only. - JWKS responses are cached.
openid-clientdoes this for you when you use@synqid/nextjs/handlers; if you’re verifying tokens in a non-Next backend, configure your verifier’s cache.
Browser & mobile clients
-
@synqid/react-nativeSecureStore is enabled. Default is AsyncStorage which is plaintext on disk on Android. - Deep link routing handles the
/oauth/callbackpath on mobile.expo-linkingconfig has it; verify the prefix and scheme match what’s registered with Synq. - CORS allowlist on your API includes the production app URL
and only the production app URL. No
*, no preview URL in production.
Final smoke test
After everything above is checked, run a clean-cookie sign-in flow end to end on production:
- Open the production app in an incognito window.
- Click “Sign in” → land on the Synq hosted login.
- Sign in via your most-used provider (Google for most teams).
- Land back on the app, signed in, with the correct user shown.
- Refresh the page — still signed in.
- Open dev tools → inspect the session cookie; verify name +
Secure+HttpOnly+SameSite=Lax. - Sign out via your sign-out flow.
- Re-open in incognito; sign in via a different provider
(Apple, Discord, etc.) — verify the same
subis linked or that the flow correctly handles a differentsubper your account-linking policy.
If steps 1–8 all pass, you’re production-ready.
Found something missing on this list? Email support@synq.id — we add to it after every incident, public or internal.
Last updated on