For Workers & Pages, what is the name of the domain?
General Guidance
What is the error number?
None
What is the error message?
None
What is the issue or error you’re encountering
None - General Advice
What steps have you taken to resolve the issue?
I am looking for advice on how I’ve set up my Cloudflare pipeline and to confirm if my security model is solid. The goal is to keep dev fast while maintaining a production-grade isolation model between the frontend and backend.
Structure:
- One React app deployed as static assets via Cloudflare Pages
- One frontend worker that catches /api* routes in the React app and proxies them internally
- One backend API worker accessed only via internal service binding
Overview of data flow:
React App → Cloudflare Pages → Worker (CSRF validation) → Service Binding (only allows internal traffic from authorized binding) → Backend API Worker
What are the steps to reproduce the issue?
-
Each React client receives a unique CSRF token that authorizes them to invoke public API routes. This is used to validate origin, enforce per-client rate limits, and block payload-based attacks like JSON enumeration or discovery probing. The CSRF has tight referer checks, rate limit, and TTL rotation.
-
The frontend worker passes requests to the API worker via a Cloudflare service binding using http://workername/ namespace. The API worker only allows traffic from this route and denies all public traffic by default. Any failed schema validation or rejected route blocklist that CSRF (threshold on 3 cumulative violations). I also broadcast a violation to WAF trough a Custom Response Header that force JS challenge for this IP tag, and block repeat offender.
-
The API worker validates that the request came from the service binding. It does not expose any public routes, except one IP-allowlisted external route that uses Bearer API key authentication for integration with third-party systems.
-
Only the backend API worker is allowed to perform authoritative operations like writing to R2, D1, or other Cloudflare services.
This gives me a simple and predictable mapping between my React frontend SDK and backend API contract.
Total roundtrip (browser call > worker CSRF > working binding > insert in D1 > response binding > response to browser) is 94 MS.
400 to 500 ms on an initial call with cold HTTPS handshake. (TLS handshake overhead is 200 - 300 ms, then it’s reused by Cloudflare and the workers are warm)
For development, Vite proxies API routes directly to the backend worker. It authenticates via IP allowlisting and injects a Bearer API key using .env.local, which is gitignored. No changes are required in frontend code between dev and prod.
Other headers are used for versioning and routing (like X-API-Version).
For long transaction, reply with the cloudflare Workflow instanceId (90 ms) and start polling for result. (Workflow multi-step orchestration with fault-tolerance)
My CSRF worker do support SSE sub (/api/workflow-events?instanceId=xyz). I also support PubSub on a DO if I need multiple client to listen to an event / workflow outcome.
So far this setup has given me very high throughput and a smooth development cycle. It took me less than a day to fully implement, automate for all my dev pipeline with repo, and build a full telemetry dashboard for request, SSE traffic, workflow execution, etc… for both dev and prod support as well as attack detection with my WAF.
90% of this is in the .toml and very few line of code in the CSRF and API worker…
I’m looking for input on:
- Is this a sound and idiomatic use of service bindings?
- Is CSRF a reliable mechanism for protecting public API routes on the edge? Any alternative?
- Any concerns or gotchas when scaling to high concurrency or larger teams?
- Any better pattern to detect or authenticate service binding calls?