Skip to content

Commit 060c48a

Browse files
committed
add changelog, shuffle sections
1 parent 6f83aa9 commit 060c48a

File tree

2 files changed

+155
-131
lines changed

2 files changed

+155
-131
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: D1 Read Replication Public Beta
3+
description: Use D1 Sessions API to leverage read replication.
4+
products:
5+
- d1
6+
date: 2025-04-04
7+
---
8+
9+
D1 read replication is available in public beta to help lower average latency and increase overall throughput for read-heavy applications like e-commerce websites or content management tools.
10+
11+
Workers can leverage read-only database copies, called read replicase, by using D1 [Sessions API](/d1/best-practices/read-replication). A Session encapsulates all the queries from one logical session for your application. For example, a Session may correspond to all queries coming from a particular web browser session. With Sessions API, D1 queries in a Session are guanranteed to be sequentially consistent(/d1/best-practices/read-replication/#replica-lag-and-consistency-model) to avoid data consistency pitfalls. D1 [bookmarks](/d1/reference/time-travel/#bookmarks) can be used from a previous Session to ensure logical consistency between Sessions.
12+
13+
```ts
14+
// retrieve bookmark from previous Session stored in HTTP header
15+
const bookmark = request.headers.get('x-d1-bookmark') ?? 'first-unconstrained';
16+
17+
const session = env.DB.withSession(bookmark)
18+
const result = await session
19+
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
20+
.run()
21+
// store bookmark for a future Session
22+
response.headers.set('x-d1-bookmark', session.getBookmark() ?? "")
23+
```
24+
25+
Read replicas are automatically created by Cloudlfare (currently one in each supported [D1 region](/d1/best-practices/read-replication/#read-replica-locations)), are active/inactive based on query traffic, and are transparently routed to by Cloudflare at no additional cost.
26+
27+
To checkout D1 read replication:
28+
29+
Deploy the following Worker code using Sessions API, which will prompt you to create a D1 database and enable read replication on said database.
30+
31+
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/staging/d1-starter-sessions-api)
32+
33+
To read more about how read replication was implemented, read our [blog post](https://blog.cloudflare.com/d1-read-replication-beta)
34+

src/content/docs/d1/best-practices/read-replication.mdx

Lines changed: 121 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,11 @@ D1 read replication can lower latency for read queries and scale read throughput
1212

1313
Your application can use read replicas with D1 [Sessions API](/d1/worker-api/d1-database/#withsession). A Session encapsulates all the queries from one logical session for your application. For example, a Session may correspond to all queries coming from a particular web browser session. All queries within a Session read from a database instance which is as up-to-date as your query needs it to be. Sessions API ensures [sequential consistency](/d1/best-practices/read-replication/#replica-lag-and-consistency-model) for all queries in a Session.
1414

15-
To checkout D1 read replication and Sessions API:
15+
To checkout D1 read replication:
1616

17-
1. Deploy the following Worker code, which will prompt you to create a D1 database.
17+
Deploy the following Worker code using Sessions API, which will prompt you to create a D1 database and enable read replication on said database.
1818

19-
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/lambrospetrou/d1-starter-sessions-api)
20-
21-
2. Enable read replication on the just created D1 database.
22-
23-
```curl
24-
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
25-
-H "Authorization: Bearer $TOKEN" \
26-
-H "Content-Type: application/json" \
27-
-d '{"read_replication": {"mode": "auto"}}'
28-
```
29-
30-
:::note
31-
To use REST API, you need to have an API token with `D1:Edit` permission.
32-
33-
If you do not have an API token, follow the guide: [Create API token](/fundamentals/api/get-started/create-token/).
34-
:::
19+
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/staging/d1-starter-sessions-api)
3520

3621
```ts collapse={1-6, 34-130}
3722
import { D1Database, D1DatabaseSession } from "@cloudflare/workers-types";
@@ -189,116 +174,25 @@ All write queries are still forwarded to the primary database instance. Read rep
189174
| Primary database instance | The database instance containing the “original” copy of the database | Can serve write queries | Can serve read queries |
190175
| Read replica database instance | A database instance containing a copy of the original database which asynchronously receives updates from the primary database instance | Forwards any write queries to the primary database instance | Can serve read queries using its own copy of the database |
191176

192-
## Use Sessions API
193-
194-
By using [Sessions API](/d1/worker-api/d1-database/#withsession) for read replication, all of your queries from a single <GlossaryTooltip term="session">Session</GlossaryTooltip> read from a version of the database which ensures sequential consistency. This ensures that the version of the database you are reading is logically consistent even if the queries are handled by different read replicas.
195-
196-
D1 read replication achieves this by attaching a <GlossaryTooltip term="bookmark">bookmark</GlossaryTooltip> to each query within a Session. For more information, refer to [Bookmarks](/d1/reference/time-travel/#bookmarks).
197-
198-
### Enable read replication
199-
200-
With the REST API, set `read_replication.mode: auto` to enable read replication on a D1 database.
201-
202-
:::note
203-
To use REST API, you need to have an API token with `D1:Edit` permission.
204-
205-
If you do not have an API token, follow the guide: [Create API token](/fundamentals/api/get-started/create-token/).
206-
:::
207-
208-
<Tabs>
209-
<TabItem label="cURL">
210-
```curl
211-
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
212-
-H "Authorization: Bearer $TOKEN" \
213-
-H "Content-Type: application/json" \
214-
-d '{"read_replication": {"mode": "auto"}}'
215-
```
216-
</TabItem><TabItem label="TypeScript">
217-
218-
```ts
219-
const headers = new Headers({
220-
"Authorization": `Bearer ${TOKEN}`
221-
});
222-
223-
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
224-
method: "PUT",
225-
headers: headers,
226-
body: JSON.stringify(
227-
{ "read_replication": { "mode": "auto" } }
228-
)
229-
}
230-
)
231-
```
232-
</TabItem>
233-
</Tabs>
234-
235-
### Disable read replication
236-
237-
With the REST API, set `read_replication.mode: disabled` to disable read replication on a D1 database.
238-
Use an [API token](/fundamentals/api/get-started/create-token/) with `D1:Edit` [permission](/fundamentals/api/reference/permissions/#account-permissions).
239-
240-
<Tabs>
241-
<TabItem label="cURL">
242-
```curl
243-
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
244-
-H "Authorization: Bearer $TOKEN" \
245-
-H "Content-Type: application/json" \
246-
-d '{"read_replication": {"mode": "disabled"}}'
247-
```
248-
</TabItem><TabItem label="TypeScript">
249-
```ts
250-
const headers = new Headers({
251-
"Authorization": `Bearer ${TOKEN}`
252-
});
177+
## Benefits of read replication
253178

254-
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
255-
method: "PUT",
256-
headers: headers,
257-
body: JSON.stringify(
258-
{ "read_replication": { "mode": "disabled" } }
259-
)
260-
}
261-
)
262-
```
263-
</TabItem>
264-
</Tabs>
179+
A system with multiple read replicas located around the world improves the performance of databases:
265180

266-
:::note
267-
Disabling read replication takes 24 hours for replicas to stop processing requests.
268-
:::
181+
- The read throughput increases by distributing load across multiple replicas. Since multiple database instances are able to serve read-only requests, your application can serve a larger number of queries at any given time.
182+
- The query latency decreases for users located close to the read replicas. By shortening the physical distance between a the database instance and the user, read query latency decreases, resulting in a faster application.
269183

270-
### Check if read replication is enabled
184+
## Use Sessions API
271185

272-
`GET` D1 database REST endpoint returns if read replication is enabled or disabled.
273-
Use an [API token](/fundamentals/api/get-started/create-token/) with `D1:Read` [permission](/fundamentals/api/reference/permissions/#account-permissions).
186+
By using [Sessions API](/d1/worker-api/d1-database/#withsession) for read replication, all of your queries from a single <GlossaryTooltip term="session">Session</GlossaryTooltip> read from a version of the database which ensures sequential consistency. This ensures that the version of the database you are reading is logically consistent even if the queries are handled by different read replicas.
274187

275-
<Tabs>
276-
<TabItem label="cURL">
277-
```curl
278-
curl -X GET "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
279-
-H "Authorization: Bearer $TOKEN"
280-
```
281-
</TabItem>
282-
<TabItem label="TypeScript">
283-
```ts
284-
const headers = new Headers({
285-
"Authorization": `Bearer ${TOKEN}`
286-
});
188+
D1 read replication achieves this by attaching a <GlossaryTooltip term="bookmark">bookmark</GlossaryTooltip> to each query within a Session. For more information, refer to [Bookmarks](/d1/reference/time-travel/#bookmarks).
287189

288-
const response = await fetch("/v4/accounts/{account_id}/d1/database/{database_id}", {
289-
method: "GET",
290-
headers: headers
291-
});
190+
### Enable read replicaton
292191

293-
const data = await response.json();
294-
console.log(data.read_replication.mode);
295-
```
296-
</TabItem>
297-
</Tabs>
192+
Read replication can be enabled at the database level in the Cloudflare dashboard. Check [**<D1 Database>** > **Settings**] to view if read replication is enabled.
298193

299-
- Check the `read_replication` property of the `result` object
300-
- `"mode": "auto"` indicates read replication is enabled
301-
- `"mode": "disabled"` indicates read replication is disabled
194+
1. Go to [**Workers & Pages** > **D1**](https://dash.cloudflare.com/?to=/:account/workers/d1).
195+
2. Select an existing database > Settings > Enable Read Replication.
302196

303197
### Start a Session without constraints
304198

@@ -509,6 +403,109 @@ console.log({
509403

510404
- `served_by_region` and `served_by_primary` fields are present for all D1 remote requests, regardless of whether read replication is enabled or if the Sessions API is used. On local development, `npx wrangler dev`, these fields are `undefined`.
511405

406+
### Enable read replication via REST API
407+
408+
With the REST API, set `read_replication.mode: auto` to enable read replication on a D1 database.
409+
410+
For this REST endpoint, you need to have an API token with `D1:Edit` permission. If you do not have an API token, follow the guide: [Create API token](/fundamentals/api/get-started/create-token/).
411+
412+
<Tabs>
413+
<TabItem label="cURL">
414+
```curl
415+
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
416+
-H "Authorization: Bearer $TOKEN" \
417+
-H "Content-Type: application/json" \
418+
-d '{"read_replication": {"mode": "auto"}}'
419+
```
420+
</TabItem><TabItem label="TypeScript">
421+
422+
```ts
423+
const headers = new Headers({
424+
"Authorization": `Bearer ${TOKEN}`
425+
});
426+
427+
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
428+
method: "PUT",
429+
headers: headers,
430+
body: JSON.stringify(
431+
{ "read_replication": { "mode": "auto" } }
432+
)
433+
}
434+
)
435+
```
436+
</TabItem>
437+
</Tabs>
438+
439+
### Disable read replication via REST API
440+
441+
With the REST API, set `read_replication.mode: disabled` to disable read replication on a D1 database.
442+
443+
For this REST endpoint, you need to have an API token with `D1:Edit` permission. If you do not have an API token, follow the guide: [Create API token](/fundamentals/api/get-started/create-token/).
444+
445+
:::note
446+
Disabling read replication takes up to 24 hours for replicas to stop processing requests. Sessions API works with databases that do not have read replication enabled, so it’s safe to run code with Sessions API even after you disable replicas.
447+
:::
448+
449+
<Tabs>
450+
<TabItem label="cURL">
451+
```curl
452+
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
453+
-H "Authorization: Bearer $TOKEN" \
454+
-H "Content-Type: application/json" \
455+
-d '{"read_replication": {"mode": "disabled"}}'
456+
```
457+
</TabItem><TabItem label="TypeScript">
458+
```ts
459+
const headers = new Headers({
460+
"Authorization": `Bearer ${TOKEN}`
461+
});
462+
463+
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
464+
method: "PUT",
465+
headers: headers,
466+
body: JSON.stringify(
467+
{ "read_replication": { "mode": "disabled" } }
468+
)
469+
}
470+
)
471+
```
472+
</TabItem>
473+
</Tabs>
474+
475+
### Check if read replication is enabled
476+
477+
`GET` D1 database REST endpoint returns if read replication is enabled or disabled.
478+
479+
For this REST endpoint, you need to have an API token with `D1:Read` permission. If you do not have an API token, follow the guide: [Create API token](/fundamentals/api/get-started/create-token/).
480+
481+
<Tabs>
482+
<TabItem label="cURL">
483+
```curl
484+
curl -X GET "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
485+
-H "Authorization: Bearer $TOKEN"
486+
```
487+
</TabItem>
488+
<TabItem label="TypeScript">
489+
```ts
490+
const headers = new Headers({
491+
"Authorization": `Bearer ${TOKEN}`
492+
});
493+
494+
const response = await fetch("/v4/accounts/{account_id}/d1/database/{database_id}", {
495+
method: "GET",
496+
headers: headers
497+
});
498+
499+
const data = await response.json();
500+
console.log(data.read_replication.mode);
501+
```
502+
</TabItem>
503+
</Tabs>
504+
505+
- Check the `read_replication` property of the `result` object
506+
- `"mode": "auto"` indicates read replication is enabled
507+
- `"mode": "disabled"` indicates read replication is disabled
508+
512509
## Read replica locations
513510

514511
Currently, D1 automatically creates a read replica in [every supported region](/d1/configuration/data-location/#available-location-hints), including the region where the primary database instance is located. These regions are:
@@ -537,14 +534,14 @@ To see the impact of read replication and check the how D1 requests are processe
537534

538535
There are some known limitations for D1 read replication.
539536

540-
- TODO: smart placemet
541-
- TBC
537+
- Sessions API is only available via the [D1 Worker Binding](/d1/worker-api/d1-database/#withsession) and not yet available via the REST API.
538+
- TODO: smart placement
542539

543540
## Background information
544541

545542
### Replica lag and consistency model
546543

547-
To account for replica lag, it is important to consider the consistency model for D1. A consistency model is a logical framework that governs how a database system serves user queries (how the data is updated and accessed) when there are multiple database instances. Different models can be useful in different use cases. Most database systems provide [read committed](https://jepsen.io/consistency/models/read-committed), [snapshot isolation](https://jepsen.io/consistency/models/snapshot-isolation), or [serializable](https://jepsen.io/consistency/models/serializable) consistency models, depending on their configuration.
544+
To account for <GlossaryTooltip term="replica lag"> replica lag </GlossaryTooltip>, it is important to consider the consistency model for D1. A consistency model is a logical framework that governs how a database system serves user queries (how the data is updated and accessed) when there are multiple database instances. Different models can be useful in different use cases. Most database systems provide [read committed](https://jepsen.io/consistency/models/read-committed), [snapshot isolation](https://jepsen.io/consistency/models/snapshot-isolation), or [serializable](https://jepsen.io/consistency/models/serializable) consistency models, depending on their configuration.
548545

549546
#### Without Sessions API
550547

@@ -582,19 +579,12 @@ Sequential consistency has properties such as:
582579
- **Writes follow reads**: If you read a value, then perform a write, the subsequent write must be based on the value that was just read.
583580
- **Read my own writes**: If you write to the database, all subsequent reads will see the write.
584581

585-
### Benefits of read replication
586-
587-
A system with multiple read replicas located around the world improves the performance of databases:
588-
589-
- The read throughput increases by distributing load across multiple replicas. Since multiple database instances are able to serve read-only requests, your application can serve a larger number of queries at any given time.
590-
- The query latency decreases for users located close to the read replicas. By shortening the physical distance between a the database instance and the user, read query latency decreases, resulting in a faster application.
591-
592582
## Supplementary information
593583

594584
You may wish to refer to the following resources:
595585

596586
- Blog: [Beta announcement & technical deep dive](https://blog.cloudflare.com/d1-read-replication-beta/)
597587
- Blog: [Building D1: a Global Database](https://blog.cloudflare.com/building-d1-a-global-database/)
598588
- [D1 Sessions API documentation](/d1/worker-api/d1-database#withsession)
599-
- [Demo application]
589+
- [D1 Sessions API starter demo](https://github.com/cloudflare/templates/tree/staging/d1-starter-sessions-api)
600590
- [E-commerce store read replication demo](/d1/demos/#demos)

0 commit comments

Comments
 (0)