The Reflex Problem in Infrastructure Selection
When a new project lands, most engineers reach for AWS without thinking. The muscle memory is understandable. AWS has the deepest service catalog, the most battle-tested tooling, and the largest talent pool. But over the last two or three years, Cloudflare's developer platform has crossed a threshold where dismissing it outright is itself a decision risk.
This article is not a product comparison table. It is a framework for deciding whether Cloudflare's design philosophy maps to your workload before you commit either way. Numbers like memory limits and storage caps change with every product update. Design philosophy does not.
The intended audience is engineers who already understand VPCs, load balancers, Lambda, S3, and RDS. If you have never touched Cloudflare Workers or R2, this is your orientation.
What Kind of Company Is Cloudflare, Actually?
The fastest path to understanding Cloudflare's developer platform is to understand where the company came from.
Cloudflare started as a CDN. Not as a compute company, not as a storage company. A content delivery network whose business model was standing between web servers and the internet, absorbing traffic, caching aggressively, and sitting physically close to users in hundreds of cities worldwide.
AWS is a compute department store. Cloudflare is compute layered thinly on top of a global network that already exists.
This single origin explains almost everything about the platform's strengths and constraints, including why they look the way they do.
Service Mapping: Cloudflare Primitives vs AWS Equivalents
Before going deeper, here is a rough mapping to orient AWS engineers:
| Role | AWS | Cloudflare |
|---|---|---|
| Compute | Lambda | Workers (+ Workflows, Containers) |
| Object storage | S3 | R2 (S3-compatible, zero egress fees) |
| Relational DB | RDS | D1 (SQLite, ~10 GB) / Hyperdrive (external DB proxy) |
| Key-value store | DynamoDB / ElastiCache | KV |
| Queue | SQS | Queues |
| Orchestration | Step Functions | Workflows |
| Containers | ECS / Fargate | Containers |
| CDN | CloudFront | Cloudflare CDN (integrated into the platform, not a separate product) |
| Stateful coordination | (no equivalent) | Durable Objects |
Durable Objects deserve special attention. There is no AWS equivalent, and they encode the most distinctive architectural idea on the platform. We will get to them shortly.
One Root, Not Five Rules
Cloudflare's constraints and advantages are often presented as a checklist: 128 MB memory limit, CPU time billing, no raw TCP ingress, zero egress fees from R2, and so on. Memorizing that list is the wrong approach. Each item traces back to a single origin point.
The root: Cloudflare built programmable compute (Workers) directly on the HTTP path of a globally distributed reverse proxy. The CDN was the product. Workers were bolted onto its request-handling pipeline.
From that root, two branches emerge simultaneously. They are siblings, not parent and child.
The first branch is ubiquity. Because the CDN already has nodes in 300-plus cities across 100-plus countries, Workers run everywhere by default. No region selection required. The entire network was already built and paid for by CDN revenue.
The second branch is HTTP-nativeness. Because the CDN was built to handle web traffic, the programmable layer sits on the HTTP path. Workers receive HTTP and WebSocket connections. They cannot receive raw TCP or UDP as a server.
From the ubiquity branch, a chain follows:
You cannot put large VMs at every edge node in 300 cities. The physical and economic constraints make it impossible. So compute must be lightweight. Cloudflare chose V8 isolates rather than containers or VMs. A single process hosts thousands of isolates, sharing resources. This is why cold starts are essentially zero. There is no VM to spin up.
Lightweight execution brings a constraint: roughly 128 MB of memory per Worker invocation (verify current limits in the official docs). There is no GPU. There is no large in-memory workspace.
Billing follows the execution model. Because multiple isolates share a thread, the platform cannot bill for wall-clock time. It bills for CPU time. I/O wait time is free. This is a substantial pricing advantage for workloads that spend most of their time waiting for database responses or external API calls.
Database design follows the same pressure. A globally distributed platform works best with data models that are horizontally partitioned by entity rather than centralized in a single large instance. This shapes D1's design (per-database SQLite, not a shared cluster) and is the foundational idea behind Durable Objects.
Why Zero Egress Fees Are Structurally Inevitable
R2's zero egress pricing is not a promotional tactic. It reflects Cloudflare's cost structure.
AWS charges for outbound data transfer because that bandwidth is a real cost. AWS buys transit capacity and resells it. When you extract data from S3, you pay for the pipe.
Cloudflare already owns the pipes. The peering agreements and backbone capacity that deliver CDN traffic to end users were built and paid for before R2 existed. Serving data from R2 over that network adds near-zero marginal cost. Making egress free is structurally honest.
There is also a competitive angle. AWS's egress pricing creates data gravity. Petabytes of data stored in S3 becomes prohibitively expensive to move out, which locks customers in. By making egress free, Cloudflare removes one of AWS's most powerful retention mechanisms.
Note: R2 is not free. Storage costs around $0.015 per GB-month, and read/write operations carry per-class pricing. "Egress is free" means outbound data transfer specifically. Get the distinction right before running cost projections.
The Durable Objects Model: Horizontal Partitioning as a First-Class Citizen
This is where Cloudflare diverges most sharply from conventional cloud thinking, and where the platform either clicks or does not click depending on your workload.
Traditional databases hide distribution from the developer. DynamoDB, CockroachDB, and Spanner present a single logical database. Internally, they handle partitioning, distributed transactions, and consensus. The developer writes as if there is one database. The cost of that abstraction is the latency and complexity of distributed coordination.
Durable Objects expose the distribution. Each entity in your system gets its own miniature stateful server: one chat room, one document, one tenant, one game session. Each Durable Object has its own storage and executes on a single thread. Cross-entity coordination is the application's responsibility, not the platform's.
You can think of Durable Objects as a globally consistent HashMap where the value is a live, stateful process. Given a key, the platform routes all requests for that key to exactly one instance, anywhere in the world. Because all requests for a given entity go to one place and execute on one thread, there is no need for external locking, no shared Redis, no optimistic concurrency retries. Consistency within an entity is free.
A concrete example: two users editing the same collaborative document. In a conventional architecture, you need a shared lock or a conflict resolution protocol. With Durable Objects, both users connect to the single global instance for that document. Operations execute sequentially on one thread. The coordination problem disappears.
The trade-off is explicit. Cross-entity operations, such as global rankings, cross-tenant aggregation, or multi-entity atomic transactions, require application-level fan-out. Cloudflare does not hide that complexity. If your workload needs to frequently query across all entities at once, this model creates friction that distributed SQL would have absorbed for you.
One placement detail matters for production: a Durable Object is created near the first request that accesses it. After that, it does not automatically migrate. Users far from that initial location experience round-trip latency for every request. Location hints can influence initial placement, but this is not automatic global proximity.
Takumi's Take: Durable Objects are the most architecturally honest primitive I have seen in a cloud platform. They make you design your aggregates correctly upfront rather than letting you get away with lazy global state. The problem is that most real applications have at least one "show me everything" query somewhere, whether it is a dashboard, a billing summary, or an admin view. That query will be painful on DO. If your product roadmap even hints at cross-tenant analytics, factor in a separate data pipeline before you commit to the DO model. Retrofitting that later is not a refactor. It is a rearchitecture.
What Fits and What Does Not
The architectural characteristics above produce clear selection criteria. The question is not whether Cloudflare is good or bad. The question is whether your workload maps naturally to its design.
Workloads That Fit
API servers and BFFs that are I/O-bound. The CPU-time billing model makes these extremely cost-effective. Time spent waiting for a database or upstream API does not appear on your bill.
Multi-tenant SaaS where each tenant's data is naturally isolated. The entity-per-Durable-Object model is purpose-built for this. Collaborative tools, document editors, per-tenant storage, chat applications.
Global content delivery at scale. R2's zero egress fee combined with edge caching means distributing static assets, images, and downloads worldwide is structurally cheaper than S3 plus CloudFront.
WebSocket-heavy applications. WebSocket upgrades from HTTP, which is why Workers can handle them natively. Real-time dashboards, live notification feeds, and collaborative cursors all fit.
Greenfield web applications with geographically distributed users. You get global distribution, TLS, zero cold starts, and automatic scaling without designing any of it.
Workloads That Do Not Fit
Machine learning model training. No GPU access. No large memory space. This is not a temporary limitation.
Long-running CPU-heavy processes. CPU time limits exist (verify current values in the docs, but plan around a five-minute ceiling on paid plans). If your process requires sustained CPU beyond that and cannot be decomposed, Workers are the wrong host.
Monolithic databases over 100 GB that cannot be partitioned. D1 tops out well below that. Hyperdrive can proxy an external Postgres instance, but that is a hybrid architecture, not a native Cloudflare solution.
Applications requiring raw TCP or UDP server ingress. UDP game servers, raw TCP IoT brokers, custom mail servers, SSH proxies. Workers cannot receive these protocols. Cloudflare does have separate products (Spectrum, Magic Transit) for L3 and L4 use cases, but those are network products, not the developer compute platform.
Workloads requiring atomic transactions spanning multiple independent systems with regulatory mandates. Cross-entity transactions are the application's problem on Cloudflare. If a regulator requires provably atomic multi-system commits, you need a platform that can deliver that guarantee at the infrastructure level.
The Middle Ground
Ordinary CRUD web applications, content management systems, authentication services, and lightweight background jobs can go either way. If none of the hard constraints above applies, Cloudflare tends to have the practical advantage:
- No region selection, no AZ design, no load balancer configuration
- Service Bindings allow Workers to call each other without crossing a network boundary, eliminating inter-service latency without a service mesh
- Resource bindings (`env.DB`, `env.BUCKET`) replace IAM roles, connection strings, and credential rotation in most cases
- First deploy reaches global production automatically
The trade-off is operational maturity. Cloudflare's observability tooling, IAM granularity, compliance certifications, and IaC coverage (Terraform) lag behind AWS. This gap is real and worth quantifying for your team before choosing.
Non-Technical Reasons to Choose AWS Anyway
Workload fit is necessary but not sufficient. These factors can override a positive technical assessment:
Vendor lock-in exposure. R2 is S3-compatible and relatively portable. But a system built around Durable Objects and Service Bindings has no meaningful migration path. There is no equivalent primitive at any other cloud provider. This is a harder lock than AWS egress pricing, because the exit cost is not financial. It is architectural.
Data residency requirements. The fact that Workers run everywhere by default is a feature for most applications and a compliance problem for regulated ones. GDPR, financial data localization rules, and healthcare data sovereignty requirements all assume you control where data physically resides. Cloudflare's Jurisdiction restrictions for D1 and Durable Objects exist but are not as mature as AWS's per-region architecture.
Hiring and talent pool. AWS engineers are abundant. Cloudflare Workers expertise is still relatively scarce. If your team needs to hire externally, or if key contributors leave, the recovery time is longer.
Audit and observability requirements. Distributed tracing, detailed audit logs, and fine-grained access controls at the infrastructure level are more mature on AWS. CloudWatch and X-Ray are not pretty, but they are deeply integrated and well-understood by compliance teams.
A Decision Framework in Plain Language
Run these checks in order. Earlier checks override later ones.
First, check the organizational gate. Does the project have data residency requirements? Is it tightly integrated with existing AWS infrastructure that would make a split expensive? Does it require compliance certifications that only AWS currently holds? If yes to any of these, the technical analysis below is secondary.
Second, check the protocol requirement. Does the application need to receive raw TCP or UDP connections as a server? If yes, Workers cannot serve that traffic.
Third, check the compute profile. Does any single operation require sustained CPU at scale that exceeds Workers' CPU time limits? Can that operation be offloaded to Containers via Queues? If not, AWS is the better host.
Fourth, check the data model. Can the data be partitioned by entity, tenant, or user? Is the total dataset within range of D1's capacity? Or does the application require cross-entity global queries as a primary access pattern? If the latter, either use Hyperdrive with an external Postgres instance, or go to RDS.
If all four checks pass cleanly, Cloudflare will almost always deliver faster global performance, lower operational overhead, and better economics for I/O-bound workloads.
D1 in Production: Three Things That Will Surprise You
D1 is SQLite hosted at the edge with read replicas distributed globally. It is the right database for many Cloudflare-native applications. But three behaviors will catch engineers coming from Postgres or MySQL.
Billing is by rows read and written, not by storage consumed. A query that scans a large table without an index will generate enormous row-read counts regardless of how little data it returns. Index design is a billing decision, not just a performance decision. An accidentally expensive query on a nearly empty database is a real scenario.
Write operations go to a single primary. Read replicas exist for global read performance, but there is replication lag. An application that writes a record and immediately reads it back through a replica may not see the write. This read-after-write inconsistency is not a bug. It is a documented trade-off. Applications that need read-after-write consistency must route those reads to the primary explicitly.
Migrations at scale are not straightforward. Applying schema changes to a single database is familiar. Applying them across thousands of per-tenant D1 databases is a distributed systems problem with partial failure, idempotency requirements, and nontrivial rollback. Plan for this before adopting the database-per-tenant pattern at any real scale.
A Note on EmDash: Cloudflare's CMS
In mid-2026, Cloudflare released EmDash in beta. It is positioned as a modern CMS built natively on the Cloudflare stack: Workers for compute, D1 for content storage, R2 for media.
The setup story is genuinely fast:
npm create emdash@latest
cd my-blog
npm run dev
Local development runs immediately. Deployment is:
npx wrangler login
npm run deploy
Workers, D1, and R2 provision automatically. A first-time user can have a globally deployed blog within a few hours without touching infrastructure configuration.
The plugin security model is notable. WordPress plugins run with essentially ambient authority over the database, filesystem, and network. EmDash plugins declare upfront which tables, APIs, and external hosts they need. Anything not declared is structurally inaccessible, not just policy-blocked. This is a meaningful security improvement for a CMS ecosystem that historically depends on third-party plugins.
EmDash also ships with an AGENTS.md file at the project root. This file documents the project structure, constraints, allowed customizations, and design intent for AI coding agents. Claude Code can read a symlinked CLAUDE.md pointing to the same file. The CMS is designed to be extended by AI-assisted development rather than by a traditional plugin marketplace. This is a significant philosophical departure from the WordPress model.
Beta caveats are real. SEO metadata fields in the admin UI did not reflect in rendered output at the time of initial testing. The plugin ecosystem does not yet exist. Engineers expecting WordPress-grade feature completeness out of the box will be disappointed. Engineers who want a minimal, secure foundation to extend with their own code, or with AI assistance, will find it more interesting.
The Framing That Actually Helps
The most useful mental model is not a feature comparison. It is this:
AWS gives you large, isolated, configurable compute in specific geographic regions. You compose complex services from that compute. Cloudflare gives you thin, fast compute that runs everywhere simultaneously, built on a network that already handles a significant fraction of global web traffic.
If your workload benefits from running close to every user simultaneously, from near-zero I/O billing, from entities that naturally self-partition, and from infrastructure that configures itself: Cloudflare will frequently be the better choice.
If your workload needs large compute, cross-entity global consistency, raw protocol access, or deep integration with an existing AWS estate: AWS is the correct answer, and forcing the workload onto Cloudflare will cost more in engineering effort than you save in infrastructure.
The principle to internalize is not a list of limits. It is the origin: a globally distributed CDN with programmable compute layered on its HTTP path. Once that clicks, the specific constraints follow logically. The current numbers are details to verify in the documentation. The design pressure is what you carry forward into your next architecture decision.