Developer platform map

Map compute and data products

Choose Workers, Pages, KV, D1, R2, Hyperdrive, and Durable Objects from workload requirements.

8 minute lesson

~~~

The Cloudflare dashboard can feel like a hardware store. Everything looks useful, and it is tempting to pick a product first and then look for a problem it could solve. Do the opposite: start from the workload, then pick the smallest product that removes the problem.

The compute side

Workers run request-driven code: a function receives a Request and returns a Response. Pages focuses on site deployments — it builds your project, publishes the static output, and can attach Functions for the few dynamic routes. If most of your site can be generated before the request arrives, Pages with static files is the cheaper, more boring choice, and boring is good in production.

The data side

Each storage product answers a different question:

KV               "what value belongs to this key?"    read-heavy, eventually consistent
D1               "which rows match this query?"       relational SQLite, constraints, joins
R2               "store and serve this file"          object storage, no egress fees
Hyperdrive       "reach my existing database fast"    connects PostgreSQL or MySQL
Durable Objects  "coordinate this one entity"         strongly consistent, single point

KV favors globally distributed reads and tolerates briefly stale values. D1 provides real relational structure: tables, indexes, transactions. R2 stores file bodies you would never put in a database row. Hyperdrive is for the PostgreSQL or MySQL database you already run elsewhere. Durable Objects add strongly coordinated state for one logical entity, like a chat room or a precise counter.

The decision inputs are the access pattern, the consistency requirement, the data size, and the ownership boundary. Product names come after the requirement, never before.

In code, they all arrive the same way — as bindings on env:

const flags = await env.CONFIG.get('flags', 'json')     // KV
const user = await env.DB.prepare('select * from users where id = ?')
  .bind(id).first()                                     // D1

One Worker can combine several bindings, but every extra product is a moving part you now operate.

Now classify these six workloads: a static site, feature flags, invoice rows, video uploads, an existing Postgres database, and a collaborative editing room. Write down the requirement first, then the product, and note any case where two products would work and what would tip the decision.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →