Production checklist
Before flipping the DNS, confirm every item below. Items link to the feature that implements them. Copy this list into your release-readiness doc and sign off item by item.
Anything unchecked is a launch blocker
Security
Federation increases the trust surface — untrusted remotes, hydration payloads, and CDN tampering are all in play. Lock each one down before going live.
- Content-Security-Policy header set on every HTML response (buildCsp) — Use strict-dynamic + a base64url nonce per response. Loose CSPs are worse than none.
- SRI integrity attribute on every remoteEntry.js script tag — Generated by federation.sri.algo = "sha384". Block-on-mismatch in production.
- RemoteAllowlist wired to getRemoteRegistry — Reject URLs outside the configured origins — defense in depth even with SRI.
- All inline state serialized via safeJsonForScript or serializeState — Both escape </script>, line-separator (U+2028) and paragraph-separator (U+2029).
- HTTPS only — HSTS header emitted with includeSubDomains + preload
- CORS restricted to known origins (no wildcard in prod)
- Secrets stored in the platform secret manager — never in .env checked in
- Rate limiting on auth endpoints (@jorvel/security rate-limit)
Observability
When a remote fails, the host blinks but the failure must be obvious to oncall. Wire metrics + errors before launch, not after the first incident.
- Error reporting adapter installed (Sentry / Rollbar / OTel)
- collectWebVitals() called in the shell bootstrap
- Structured logger writing JSON to a collector
- Alerts configured for error rate, p95 LCP, remote-load error rate — Set the threshold above noise but below user-visible degradation.
- onRemoteLoad telemetry feeds the same RUM pipeline as page metrics
- Source maps uploaded to the error tracker (gated behind the build hash)
- jorvel version printed in every error report (audit trail)
Performance
Each remote pays a network round-trip on first load. Budget it, monitor it, and reject regressions in CI.
- jorvel perf budgets green in CI
- Bundle analyzer (jorvel analyze) reviewed before each release
- Remote preload tags in SSR head (remoteEntryPreloads)
- Cache-Control tuned per route (cacheControl helper) — Immutable for hashed assets; short max-age for HTML; SWR for remote manifests.
- Assets hashed and served with immutable cache-control
- Compression (gzip + brotli) enabled at the edge
- Image derivatives generated for every breakpoint (jorvel image)
- Fonts preloaded with crossorigin=anonymous
Reliability
A remote crash should be a tile-level failure, not a page-level failure. Boundaries, health checks, fallbacks.
- Health check endpoint per remote — fetchHealth() can gate a load — fast-fail beats a 30s timeout.
- RemoteRegistry fetches manifest with retry + exponential backoff
- Error boundary around every RemoteOutlet
- Version mismatch warnings surfaced in logs (checkRuntimeVersions)
- Graceful fallback UI when a remote fails to load
- Blue/green or weighted-remote rollout for risky changes
- Service Worker offline fallback page tested end-to-end
Deploy
Production parity matters — the staging environment should diverge in data, not in topology.
- Adapter scaffolded (Vercel / Cloudflare / Node / Docker)
- CDN publicPath set in jorvel.config.json
- Preview deploy per PR (jorvel ci affected)
- Rollback plan documented and rehearsed
- Smoke tests run against the deploy URL before flipping DNS
- CDN cache purged on release (or version-namespaced URLs)
Release process
Predictable releases need predictable artifacts. Changesets + SemVer + tags carry the audit trail.
- Changesets workflow on main
- SemVer for every published package
- CHANGELOG.md per package up to date
- Git tags for each release
- Linked packages bump together: [runtime, ssr, security] etc.
- Release notes posted to the team channel before flipping flags
Release-day runbook
- T-24h: changeset PR merged. CI green. Preview deploy hit by team for smoke checks.
- T-1h: announce in the team channel. Page the on-call to standby. Roll forward the feature flag to off-for-everyone.
- T-0: tag the release. CI publishes packages + deploys the host + each remote. Wait for the deploy job to complete.
- T+5m:run smoke tests against production URLs. Confirm error rate flat, LCP flat, remote-load error rate < baseline.
- T+10m: flip the feature flag to 10%. Watch the dashboards.
- T+30m: if metrics are clean, ramp to 50%. Otherwise revert.
- T+60m: ramp to 100%. Close the release ticket. Post a summary with deltas in error rate, LCP, and bundle size.
Rollback plan
- Feature-flag revert first if the issue is gated. Sub-minute mitigation.
- Deploy revert — re-deploy the previous tag via the platform UI. ~3 min.
- CDN cache purge if the issue is a stale chunk. The SW will pick up the new bytes on next visit; for in-session users, broadcast a refresh prompt.
- Hotfixonly if revert isn't an option. Branch from the released tag, cherry-pick the fix, ship through the same pipeline.
