---
title: "Cloudflare flagship stack"
description: "The current architecture and operating standard for new MNPPI projects on Cloudflare."
url: "https://architecture.mnppi.org/architecture/cloudflare-flagship-stack/"
status: "Current"
last_updated: "2026-07-23"
---

# Cloudflare flagship stack

The default stack and operating controls for new MNPPI projects on Cloudflare.

**Standard details**

- Status: Current
- Reviewed: July 23, 2026
- Cadence: Review each quarter
- Source: org-standards

## 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

`demo-crm` is the reference application for the single-Worker profile.

The application uses:

- React and Vite for the application interface.
- Workers Static Assets for the client build.
- Hono for same-origin application programming interfaces.
- D1 through the application-owned Drizzle database boundary.
- R2, KV, and Cloudflare rate limiting for bounded platform services.
- GitHub Actions for required pre-merge checks.
- Cloudflare Workers Builds for the production build and deployment.

The reference application does not require each optional service.
Each project must select only the services that its profile needs.

## Scope

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

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

`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

| 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

### 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

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

GitHub Actions must use:

- Read-only permissions by default.
- Job-specific write permissions.
- Full commit identifiers for actions and reusable workflows.
- `persist-credentials: false` for 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

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

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](https://architecture.mnppi.org/operations/runner-security/) with the internal runner topology and pilot records.

## Cloudflare build and deployment contract

### 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

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

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

### Release phases

Use three release phases:

1. GitHub validates the proposed change.
2. Cloudflare builds and deploys the approved commit.
3. 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

A Worker rollback does not restore D1, KV, R2, Queue, or Durable Object state.

Use expand-and-contract database changes:

1. Add the new structure.
2. Deploy code that supports the old and new structure.
3. Migrate or backfill data.
4. Verify the new structure.
5. 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

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

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

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

Use `wrangler.jsonc` as the committed configuration source.

New Workers must use:

- A current `compatibility_date`.
- The `nodejs_compat` compatibility flag.
- Generated binding types from `wrangler types`.
- Explicit environment bindings.
- Explicit environment variables.
- Explicit routes and domains.
- Explicit `workers_dev` and 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

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

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

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

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

### 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

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

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

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

### 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

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

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

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

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

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

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 --check` passes.
- 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.

`demo-crm` is the reference application for the application stack.
Each adopting project must pass its applicable gates before production use.

## Primary references

### Cloudflare

- [Cloudflare Workers best practices](https://developers.cloudflare.com/workers/best-practices/workers-best-practices/)
- [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/)
- [Static Asset routing](https://developers.cloudflare.com/workers/static-assets/routing/worker-script/)
- [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/)
- [Workers Vitest integration](https://developers.cloudflare.com/workers/testing/vitest-integration/)
- [Workers Builds](https://developers.cloudflare.com/workers/ci-cd/builds/)
- [Workers Builds configuration](https://developers.cloudflare.com/workers/ci-cd/builds/configuration/)
- [Workers limits](https://developers.cloudflare.com/workers/platform/limits/)
- [Workers Logs](https://developers.cloudflare.com/workers/observability/logs/workers-logs/)
- [Workers Traces](https://developers.cloudflare.com/workers/observability/traces/)
- [Workers rollbacks](https://developers.cloudflare.com/workers/versions-and-deployments/rollbacks/)
- [Gradual deployments](https://developers.cloudflare.com/workers/versions-and-deployments/gradual-deployments/)
- [D1 migrations](https://developers.cloudflare.com/d1/reference/migrations/)
- [D1 Time Travel](https://developers.cloudflare.com/d1/reference/time-travel/)
- [D1 read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/)
- [Queue delivery guarantees](https://developers.cloudflare.com/queues/reference/delivery-guarantees/)
- [Workflow rules](https://developers.cloudflare.com/workflows/build/rules-of-workflows/)
- [Durable Object migrations](https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/)
- [Drizzle with Cloudflare D1](https://orm.drizzle.team/docs/connect-cloudflare-d1)

### GitHub

- [GitHub secure use reference](https://docs.github.com/en/actions/reference/security/secure-use)
- [Organization rulesets](https://docs.github.com/en/organizations/managing-organization-settings/creating-rulesets-for-repositories-in-your-organization)
- [Repository custom properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization)
- [Merge queues](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue)
- [Self-hosted runners](https://docs.github.com/en/actions/reference/runners/self-hosted-runners)
- [Runner group access](https://docs.github.com/en/actions/how-tos/manage-runners/self-hosted-runners/manage-access)
- [Just-in-time runner API](https://docs.github.com/en/rest/actions/self-hosted-runners)
