Cloudflare flagship stack
The default stack and operating controls for new MNPPI projects on Cloudflare.
Standards summary
Section titled “Standards summary”The current MNPPI core stack remains the default Cloudflare architecture.
Keep pnpm, Workers Static Assets, Astro, React, Vite, Hono, D1, Drizzle, and Cloudflare-native services.
This standard adds required controls for:
- GitHub governance.
- Continuous integration.
- Self-hosted runners.
- Cloudflare build and deployment.
- Release recovery.
- Route exposure.
- Runtime configuration.
- Application programming interfaces.
- Database changes.
- Authentication and authorization.
- Background work.
- Observability.
- Resource budgets.
The architecture standard is current. Each adopting project must pass the applicable acceptance checks.
Reference application status
Section titled “Reference application status”SeekTheChurch completed its dev and staging migration on 2026-07-23.
It retired Next.js and OpenNext from the application build.
The staging application now uses:
- Astro static output for help and legal pages.
- React and Vite for the shared-state application.
- Workers Static Assets with scoped Worker-first paths.
- Hono for same-origin application programming interfaces.
- D1 through the app-owned Drizzle database boundary.
- Cloudflare Workers Builds for the app and isolated ingest Worker.
The protected main branch and production environment have not completed cutover.
The remaining standard gates are listed in the acceptance section.
This standard applies to new MNPPI production projects that use Cloudflare Workers.
Existing projects adopt the controls through a measured migration. Do not force a framework migration when the current architecture remains safe and supported.
Each project must record its selected profile:
- Static site.
- Static site with Worker application programming interfaces.
- Interactive single-page application.
- Multi-Worker application.
- Background-processing application.
- Stateful application.
- High-risk application.
A high-risk application handles money, regulated data, privileged administration, or destructive automation. High-risk projects can use stricter controls than this baseline.
Policy terms
Section titled “Policy terms”The terms must and must not identify required controls.
The term should identifies the normal choice.
An approved exception can replace a should rule.
An exception to a must rule requires:
- One named owner.
- One documented reason.
- A limited scope.
- A review date.
- A rollback plan.
- An expiration or permanent decision.
Control ownership
Section titled “Control ownership”MNPPI/org-standards owns the versioned desired state.
It owns:
- Required workflows.
- Repository ruleset definitions.
- Repository properties.
- Renovate policy.
- Runner policy.
- Cloudflare configuration records.
- Governance and drift audits.
- Reference applications.
- Exception records.
GitHub rulesets provide live merge enforcement. Cloudflare Workers Builds provides live production build and deployment.
Documentation alone does not prove enforcement. Audits must compare the desired state with live GitHub and Cloudflare settings.
Proposed stable baseline
Section titled “Proposed stable baseline”| Layer | Organization standard |
|---|---|
| Package manager | pnpm workspaces with a pinned package manager |
| Runtime | Cloudflare Workers with a current compatibility date |
| Static delivery | Workers Static Assets with asset-first routing |
| Static pages | Astro static output |
| Interactive application | React with Vite |
| Small interactions | Astro with React islands |
| Cloudflare development | @cloudflare/vite-plugin for Vite Worker projects |
| Worker tests | @cloudflare/vitest-pool-workers |
| Client server state | TanStack Query when the application needs remote-state management |
| Client routing | TanStack Router for new non-trivial single-page applications |
| HTTP API | Hono with Zod validation |
| Database | D1 through a database package that uses Drizzle |
| Object storage | R2 |
| Configuration cache | KV only for suitable eventual-consistency use |
| Background work | Queues for buffered work and Workflows for durable multi-step work |
| Stateful coordination | Durable Objects for serialized per-entity state |
| Staff authentication | Cloudflare Access |
| Public authentication | Magic links for verification or Better Auth for application sessions |
| Styling | Tailwind CSS v4 with shadcn/ui and approved design tokens |
| Merge authority | GitHub Actions and GitHub rulesets |
| Release build | Cloudflare Workers Builds |
| Production deployment | Cloudflare Workers Builds |
| Observability | Workers Logs, release metadata, runtime measures, and approved trace pilots |
GitHub merge contract
Section titled “GitHub merge contract”Protected pull requests
Section titled “Protected pull requests”Every protected branch must require a pull request.
The organization uses a sole-owner merge model. The repository owner can merge their own pull request after all required checks pass.
The baseline requires:
- Zero approving reviews.
- All required checks to pass.
- The branch to be current.
- All review conversations to be resolved.
- No force pushes.
- No protected-branch deletion.
- No ruleset bypass actors.
- Squash merge.
- Linear history.
Do not require Code Owner approval. Do not add a required deployment reviewer that blocks the sole owner.
Rulesets should target ~DEFAULT_BRANCH.
Protect every non-default production or promotion branch explicitly.
Repositories that use merge queues must run required workflows for pull_request and merge_group.
Stable required check
Section titled “Stable required check”Each repository must expose one stable aggregate check.
The aggregate must:
- Run for every protected pull request.
- Use
if: always()when it depends on other jobs. - Reject every unsuccessful mandatory dependency.
- Keep one stable check name.
- Avoid path-based absence.
- Exclude advisory checks from its success decision.
Cloudflare build results must not replace the GitHub merge check.
Workflow security
Section titled “Workflow security”GitHub Actions must use:
- Read-only permissions by default.
- Job-specific write permissions.
- Full commit identifiers for actions and reusable workflows.
persist-credentials: falsefor checkout.- Frozen dependency installation.
- Time limits for every job.
- Concurrency controls where duplicate work has a cost or side effect.
Privileged workflows must not execute untrusted pull-request code.
Do not use pull_request_target to check out and run pull-request content.
Mandatory jobs must not use continue-on-error.
Secrets must exist only in the job or step that needs them.
Continuous integration checks
Section titled “Continuous integration checks”Each project must select all applicable checks:
- Tokenless frozen installation.
- Formatting.
- Lint.
- Type checking.
- Unit tests.
- Worker runtime integration tests.
- Application build validation.
- Local D1 migration validation.
- Static-route Worker-invocation tests.
- Wrangler package dry run.
- Workflow syntax and security checks.
- Secret scanning.
- Dependency vulnerability review.
- Software bill of materials generation when useful.
- Bundle and startup-time budgets.
A GitHub validation build is disposable. Cloudflare creates the authoritative production build.
Self-hosted runner contract
Section titled “Self-hosted runner contract”Private trusted repositories can use MNPPI self-hosted runners. Public repositories and fork pull requests must use standard GitHub-hosted runners.
Jobs must use an approved runner group and purpose label. Runner labels identify routing. They do not prove isolation.
The current persistent pool is a documented migration state. The future pool should use one-job, just-in-time runners.
Disposable runners must:
- Use one clean environment for each job.
- Run as a non-root host user.
- Avoid the host Docker socket.
- Avoid privileged containers.
- Avoid host directory mounts.
- Apply resource limits.
- Remove the container and workspace after the job.
- Forward diagnostic logs.
- Keep production credentials off the host.
Queued jobs must wait for their designated runner. Do not change labels, runners, or execution locations to bypass a queue. Do not cancel and resubmit jobs to improve queue position.
Use the public runner security standard with the internal runner topology and pilot records.
Cloudflare build and deployment contract
Section titled “Cloudflare build and deployment contract”Authority split
Section titled “Authority split”GitHub Actions decides whether code can merge. Cloudflare Workers Builds builds and deploys approved commits.
GitHub Actions must not contain the normal production deployment path. GitHub Actions must not contain routine production Cloudflare credentials.
Routine local production deployment is prohibited. An emergency command requires a documented break-glass procedure.
Workers Builds configuration
Section titled “Workers Builds configuration”Production Workers Builds must use:
- The actual protected production branch.
- An explicit project root.
- Pinned Node.js, pnpm, and Wrangler versions.
- A tokenless frozen installation.
- A minimal build command.
- A deployment command that contains only approved release operations.
- Reviewed build watch paths.
- A dedicated least-privilege Cloudflare user token.
Cloudflare currently requires a user token for Workers Builds. Record this as an exception to the normal account-token preference.
Disable non-production branch builds by default. Disable Deploy Hooks by default. Treat a Deploy Hook address as a bearer credential.
Build watch paths control cost and noise. They are not a security boundary.
org-standards must record and audit:
- Repository.
- Branch.
- Root directory.
- Build command.
- Deployment command.
- Watch paths.
- Runtime versions.
- Token owner.
- Worker name.
- Environment.
A retried build uses the current Cloudflare settings. The release record must identify the settings version used for the retry.
Lightweight release record
Section titled “Lightweight release record”Normal flagship projects do not require artifact signing or attestation.
Record these identifiers when Cloudflare provides them:
- Git commit.
- Cloudflare build identifier.
- Worker version identifier.
- Deployment time.
- Health-check result.
Do not add exact-byte proof unless a customer, regulation, or high-risk profile requires it.
Release and recovery contract
Section titled “Release and recovery contract”Release phases
Section titled “Release phases”Use three release phases:
- GitHub validates the proposed change.
- Cloudflare builds and deploys the approved commit.
- Runtime checks verify identity and health.
A post-deployment failure is a release incident. It is not a failed merge check.
Each project must define:
- A health check.
- An error threshold.
- A latency threshold.
- A rollback trigger.
- A forward-recovery path.
- A release owner.
High-risk Workers should use version upload, smoke tests, and gradual promotion.
Data recovery
Section titled “Data recovery”A Worker rollback does not restore D1, KV, R2, Queue, or Durable Object state.
Use expand-and-contract database changes:
- Add the new structure.
- Deploy code that supports the old and new structure.
- Migrate or backfill data.
- Verify the new structure.
- Remove the old structure in a later release.
Do not include an automatic destructive migration in a normal deployment.
Risky D1 changes require:
- A reviewed migration.
- Local continuous integration validation.
- A Time Travel bookmark.
- Old and new code compatibility.
- A forward-recovery plan.
Static delivery and route exposure
Section titled “Static delivery and route exposure”Workers Static Assets must serve a matching public asset before Worker code runs.
Use assets.run_worker_first as a path-pattern array for reviewed dynamic paths.
Do not set run_worker_first: true for a complete site without measured evidence.
Each route inventory must record:
- Delivery type.
- Allowed methods.
- Authentication.
- Authorization.
- Cache policy.
- Worker invocation.
- Failure response.
- Owner.
Set html_handling explicitly.
Set not_found_handling explicitly.
An unknown application programming interface route must not return the single-page application shell.
Test that representative public assets do not invoke the Worker. Confirm the result with post-deployment analytics.
_headers applies to Static Asset responses.
Worker-generated responses must set their own security headers.
Cloudflare Access
Section titled “Cloudflare Access”Cloudflare Access protects configured hostnames and paths. It does not automatically protect every project address.
Set workers_dev and preview_urls explicitly for every environment.
Disable them when they are not needed.
Otherwise, apply equivalent Access controls.
Cloudflare Access authenticates a caller. Application code must still enforce authorization.
Cloudflare development and testing
Section titled “Cloudflare development and testing”Use @cloudflare/vite-plugin for Vite Worker projects.
The Vite plugin runs Worker code in workerd during vite dev and vite preview.
It does not provide the Worker test runtime by itself.
Use @cloudflare/vitest-pool-workers for Worker integration tests.
Maintain one reference application. It must prove:
- Vite.
- React.
- Hono.
- Static Assets.
- Worker bindings.
- Environment selection.
- Local tests.
- Production packaging.
Vite selects a Cloudflare environment during the build. Do not assume a later Wrangler environment flag changes an already built output.
Runtime configuration
Section titled “Runtime configuration”Use wrangler.jsonc as the committed configuration source.
New Workers must use:
- A current
compatibility_date. - The
nodejs_compatcompatibility flag. - Generated binding types from
wrangler types. - Explicit environment bindings.
- Explicit environment variables.
- Explicit routes and domains.
- Explicit
workers_devand preview settings.
Do not maintain a hand-written Worker Env interface.
Run wrangler types --check in continuous integration.
Bindings and variables do not automatically inherit between environments. Test every staging and production binding name.
Store runtime secrets through Cloudflare secret controls.
Do not store a secret value in vars.
Local values must use ignored files and the MNPPI Keychain and direnv pattern.
Frontend composition
Section titled “Frontend composition”Use Astro as the static default. Use React islands for small interactive sections. Use a React single-page application for a shared client-state application.
Use TanStack Query when the application needs remote-state caching, retries, or invalidation. Do not add it to a static page without a product need.
Use TanStack Router for a new non-trivial single-page application. Do not replace a correct framework router without a migration reason.
Allow one combined Worker deployment when it keeps routing simple. Use separate Workers when security, ownership, or scale requires isolation.
Application programming interface contract
Section titled “Application programming interface contract”Use Hono for new HTTP application programming interfaces. Use Zod at every untrusted boundary.
Validate:
- Path parameters.
- Query parameters.
- Request bodies.
- Relevant headers.
- Webhook messages.
- Queue messages.
- Environment values.
Set request size and content-type limits.
Mutating endpoints must define:
- Authentication.
- Authorization.
- Idempotency.
- Error responses.
- Timeout behavior.
- Retry behavior.
Use Hono typed clients inside the same repository. Publish OpenAPI for an independent client, integration, or long-lived shared contract.
Use Cloudflare bindings instead of Cloudflare REST calls from Worker code. Use service binding remote procedure calls between Workers.
A service binding is a trusted transport. The receiving Worker must still enforce its caller and operation policy.
Authentication and application security
Section titled “Authentication and application security”Use Cloudflare Access for workforce identity. Do not use it as the complete application authorization system.
Application sessions must define:
- Secure and HTTP-only cookies.
- SameSite behavior.
- Session expiration.
- Session revocation.
- Cross-Site Request Forgery protection.
- Account recovery.
- Replay protection.
Public authentication must limit enumeration and repeated attempts. Use Turnstile or another approved abuse control where measured risk requires it.
Every public application must define:
- Cross-Origin Resource Sharing policy.
- Content Security Policy.
- Security headers.
- Rate limits.
- Webhook signature validation.
- Webhook replay prevention.
Database contract
Section titled “Database contract”Feature code must use the project database package. The database package should use Drizzle for normal D1 queries.
Direct D1 access outside the database package is prohibited.
The database package can use a reviewed D1 platform application programming interface when Drizzle lacks a required function. It can also use reviewed parameterized SQL.
Each exception must include:
- The missing Drizzle capability.
- The contained implementation location.
- Tests.
- An owner.
- A review date.
Drizzle Kit should generate committed migration files. Review every generated migration.
Do not change a migration after an environment applies it. Hand-authored migration SQL is allowed when a safe change requires it.
Use db.batch() for supported atomic groups.
Review indexes and query plans for critical queries.
Set rows-read and rows-written budgets for high-volume paths.
D1 read replication requires the Sessions API. Keep it as an organization pilot until the database package supports the required consistency model.
Background-work contract
Section titled “Background-work contract”Queues
Section titled “Queues”Cloudflare Queues provide at-least-once delivery.
Every Queue consumer must:
- Be idempotent.
- Set retry limits.
- Use a dead-letter queue in production.
- Handle poison messages.
- Use partial acknowledgement when suitable.
- Monitor depth, age, retries, and dead-letter growth.
Workflows
Section titled “Workflows”Use Workflows for durable multi-step operations.
Workflow steps must:
- Be deterministic.
- Be idempotent.
- Await each step.
- Remain compatible with active instances.
- Keep side effects inside reviewed step boundaries.
Durable Objects
Section titled “Durable Objects”Use Durable Objects for serialized per-entity state.
Do not use one global object for unrelated tenants. New Durable Objects should use SQLite storage and remote procedure calls.
Alarms must be idempotent. Durable Object migrations require a separate release review. Class deletion can permanently delete state.
Use waitUntil() only for short, best-effort post-response work.
Do not use it for required business processing.
Observability
Section titled “Observability”Workers Logs are required in production. Automatic Workers Traces remain a controlled pilot.
Each project must define:
- Log sampling by environment.
- Trace sampling when traces are enabled.
- Personal-data and secret redaction.
- Release and Worker version fields.
- Error alerts.
- Latency alerts.
- Retention or export.
- A telemetry cost budget.
Use structured log records. Do not write secret values, session tokens, or unnecessary personal data.
Resource and release budgets
Section titled “Resource and release budgets”Pre-deployment gates
Section titled “Pre-deployment gates”GitHub continuous integration must record:
- Compressed Worker size.
- Worker startup time.
- Static-route invocation proof.
- Binding and type validation.
- Platform-limit validation.
The organization warning threshold is 50 percent of the applicable bundle ceiling. The organization blocking threshold is 75 percent of that ceiling.
The startup-time warning threshold is 500 milliseconds. The startup-time blocking threshold is 750 milliseconds.
Projects can set stricter limits.
Runtime gates
Section titled “Runtime gates”Runtime monitoring must record:
- CPU p50, p95, and p99.
- Request errors and exceptions.
- Latency.
- Memory pressure.
- Subrequest use.
- Queue backlog.
Each Worker must set an approved limits.cpu_ms value.
Set the value from the route class and measured workload.
The project must set numeric CPU and latency budgets before production. Do not copy one CPU value into every application.
Static asset requests must not invoke Worker code unless a reviewed route requires it.
Platform adoption policy
Section titled “Platform adoption policy”Being current does not require every new Cloudflare feature. Use stable features after reference validation. Use preview or beta features through measured pilots.
| Feature | Organization position | Decision |
|---|---|---|
| Vite 8 | Current stable | Adopt after the reference application passes. |
| Cloudflare Vite plugin | Approved | Use for Vite Worker projects. |
| Workers Static Assets | Approved | Use for new sites and asset-heavy applications. |
| Workers Builds | Approved with audit | Use for production build and deployment after protected merges. |
| Workers Logs | Approved | Require in production. |
| Automatic Workers Traces | Beta | Use through an approved sampling and cost pilot. |
| Workers Vitest integration | Beta tooling | Use for Worker-runtime tests and track known limitations. |
| D1 read replication | Organization pilot | Require Sessions API support and a defined consistency model. |
| Smart Placement | Beta | Pilot only when latency and CPU data can show the result. |
| Secrets Store | Open beta | Track it and keep Worker secrets as the baseline. |
| Workflows | Approved with budget | Use for durable multi-step work with cost and recovery controls. |
| Durable Objects with SQLite | Approved | Use for new per-entity state. |
| TanStack Start on Workers | Supported option | Use only when the product proves a server-render requirement. |
| React Server Components | Controlled option | Do not use as the static-first baseline. |
Pilot requirements
Section titled “Pilot requirements”A platform pilot must:
- Have one owner.
- Have one reversible scope.
- Define success measures.
- Define rollback measures.
- Measure CPU, latency, errors, cost, and operating effort.
- Avoid unnecessary production data risk.
- Produce a written adoption decision.
Dependency review snapshot
Section titled “Dependency review snapshot”These versions were current in the public package registry on 2026-07-22. They are review evidence and not permanent policy pins.
| Package | Reviewed version |
|---|---|
| React | 19.2.8 |
| Vite | 8.1.5 |
| Astro | 7.1.3 |
| Hono | 4.12.31 |
| Drizzle ORM | 0.45.2 |
| Drizzle Kit | 0.31.10 |
@cloudflare/vite-plugin |
1.46.0 |
| Wrangler | 4.113.0 |
| TanStack Query | 5.101.4 |
| TanStack Router | 1.170.18 |
| Tailwind CSS | 4.3.3 |
| shadcn | 4.14.0 |
Use Renovate and the reference application to keep approved versions current. Do not copy this version snapshot into a permanent package policy.
Governance lifecycle
Section titled “Governance lifecycle”Review this standard:
- Every quarter.
- After a material Cloudflare platform change.
- After a material GitHub Actions change.
- After a Node.js, pnpm, Vite, or framework major release.
- After a significant security incident.
Each review must record:
- Review date.
- Owner.
- Primary sources.
- Changed decisions.
- Deprecated decisions.
- Active exceptions.
- Required migrations.
Acceptance gates
Section titled “Acceptance gates”A project can claim conformance with this standard when:
- One reference application passes the approved Vite test matrix.
- Static routes show no Worker invocation.
- Dynamic routes use explicit path patterns.
- Unknown application programming interface routes do not return an application shell.
- Runtime database code follows the database-package boundary.
- Every migration passes local validation.
wrangler types --checkpasses.- Workers Logs are enabled.
- Resource budgets have numeric project values.
- GitHub enforces the merge contract.
- The repository owner can merge their own pull request after checks pass.
- The just-in-time runner canary passes and cleans itself.
- Workers Builds is the only normal production build and deployment authority.
- The release record links the commit, build, version, and health result.
- The rollback and data-recovery runbooks pass a review.
SeekTheChurch completed the architecture migration while this candidate standard was under review. Its final delta review must close the remaining gates before production cutover.
Primary references
Section titled “Primary references”Cloudflare
Section titled “Cloudflare”- Cloudflare Workers best practices
- Workers Static Assets
- Static Asset routing
- Cloudflare Vite plugin
- Workers Vitest integration
- Workers Builds
- Workers Builds configuration
- Workers limits
- Workers Logs
- Workers Traces
- Workers rollbacks
- Gradual deployments
- D1 migrations
- D1 Time Travel
- D1 read replication
- Queue delivery guarantees
- Workflow rules
- Durable Object migrations
- Drizzle with Cloudflare D1