diff --git a/src/content/docs/d1/observability/debug-d1.mdx b/src/content/docs/d1/observability/debug-d1.mdx index b093e67d6f4..4261741c6d3 100644 --- a/src/content/docs/d1/observability/debug-d1.mdx +++ b/src/content/docs/d1/observability/debug-d1.mdx @@ -118,3 +118,25 @@ You should include as much of the following in any bug report: * Learn [how to debug Workers](/workers/observability/). * Understand how to [access logs](/workers/observability/logs/) generated from your Worker and D1. * Use [`wrangler dev`](/workers/wrangler/commands/general/#dev) to run your Worker and D1 locally and [debug issues before deploying](/workers/local-development/). + +## D1 binding timeout behavior + +D1 binding methods — `run()`, `all()`, `first()`, and `batch()` — do not accept a timeout option or an `AbortSignal`. There is no per-call timeout built into the D1 binding client. + +Workers have no wall-time limit on incoming HTTP requests while the client connection is open — see [Workers limits](/workers/platform/limits/). If the D1 database is temporarily unreachable, a D1 binding call blocks until the operation completes, an internal limit is reached, or the Worker is terminated by an external event such as the client disconnecting. + +To limit how long your Worker waits on a D1 call, use `Promise.race` with a timer: + +```js +const timeout = new Promise((_, reject) => + setTimeout(() => reject(new Error('D1 call timed out')), 5000) +); +const result = await Promise.race([ + db.prepare('SELECT 1').first(), + timeout, +]); +``` + +:::caution[Write operations and Promise.race] +`Promise.race` bounds how long your Worker waits — it does not cancel the D1 query. A write that loses the race may still commit in the background. Always confirm the outcome of a write before retrying to avoid duplicate writes. +:::