---
description: Use the scheduler.wait() API to delay execution in Workers.
title: Scheduler
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt  
> Use this file to discover all available pages before exploring further.

# Scheduler

Last updated Aug 25, 2026|Copy as Markdown|[View as Markdown](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/scheduler/index.md)|[Agent setup](https://66f4ea29.previews.developers.cloudflare.com/agent-setup/)

## Background

The `scheduler` global provides task scheduling APIs based on the [WICG Scheduling APIs proposal ↗](https://github.com/WICG/scheduling-apis). Workers currently implement the `scheduler.wait()` method.

`scheduler.wait()` returns a Promise that resolves after a given number of milliseconds. It is an `await`\-able alternative to `setTimeout()` that does not require a callback.

Like other [timers in Workers](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/web-standards/#timers), `scheduler.wait()` does not advance during CPU execution when deployed to Cloudflare. This is a [security measure to mitigate against Spectre attacks](https://66f4ea29.previews.developers.cloudflare.com/workers/reference/security-model/#step-1-disallow-timers-and-multi-threading). In local development, timers advance regardless of whether I/O occurs.

## Syntax

```js
await scheduler.wait(delay);
await scheduler.wait(delay, options);
```

## Parameters

* `delay` number

  * The number of milliseconds to wait before the returned Promise resolves.
* `options` object optional

  * Optional configuration for the wait operation.
  * `signal` AbortSignal optional

    * An [AbortSignal](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/web-standards/#abortcontroller-and-abortsignal) that cancels the wait. When the signal is aborted, the returned Promise rejects with an `AbortError`.

## Return value

A `Promise<void>` that resolves after `delay` milliseconds. If an `AbortSignal` is provided and aborted before the delay elapses, the Promise rejects with an `AbortError`.

## Examples

### Basic delay

Use `scheduler.wait()` to pause execution for a specified duration.

```js
export default {
	async fetch(request) {
		// Wait for 1 second
		await scheduler.wait(1000);
		return new Response("Delayed response");
	},
};
```

```ts
export default {
	async fetch(request): Promise<Response> {
		// Wait for 1 second
		await scheduler.wait(1000);
		return new Response("Delayed response");
	},
} satisfies ExportedHandler;
```

### Retry with exponential backoff

Use `scheduler.wait()` to implement a delay between retry attempts. This example uses exponential backoff with jitter.

```js
async function fetchWithRetry(url, maxAttempts = 3) {
	const baseBackoffMs = 100;
	const maxBackoffMs = 10000;

	for (let attempt = 0; attempt < maxAttempts; attempt++) {
		try {
			return await fetch(url);
		} catch (err) {
			if (attempt + 1 >= maxAttempts) {
				throw err;
			}
			const backoffMs = Math.min(
				maxBackoffMs,
				baseBackoffMs * Math.random() * Math.pow(2, attempt),
			);
			await scheduler.wait(backoffMs);
		}
	}
	throw new Error("unreachable");
}

export default {
	async fetch(request) {
		const response = await fetchWithRetry("https://example.com/api");
		return new Response(response.body, response);
	},
};
```

```ts
async function fetchWithRetry(url: string, maxAttempts = 3): Promise<Response> {
	const baseBackoffMs = 100;
	const maxBackoffMs = 10000;

	for (let attempt = 0; attempt < maxAttempts; attempt++) {
		try {
			return await fetch(url);
		} catch (err) {
			if (attempt + 1 >= maxAttempts) {
				throw err;
			}
			const backoffMs = Math.min(
				maxBackoffMs,
				baseBackoffMs * Math.random() * Math.pow(2, attempt),
			);
			await scheduler.wait(backoffMs);
		}
	}
	throw new Error("unreachable");
}

export default {
	async fetch(request): Promise<Response> {
		const response = await fetchWithRetry("https://example.com/api");
		return new Response(response.body, response);
	},
} satisfies ExportedHandler;
```

### Cancel with AbortSignal

Use an [AbortController](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/web-standards/#abortcontroller-and-abortsignal) to cancel a pending wait.

```js
export default {
	async fetch(request) {
		const controller = new AbortController();

		// Cancel the wait after 500ms
		setTimeout(() => controller.abort(), 500);

		try {
			await scheduler.wait(5000, { signal: controller.signal });
			return new Response("Wait completed");
		} catch (err) {
			if (err instanceof DOMException && err.name === "AbortError") {
				return new Response("Wait was cancelled", { status: 408 });
			}
			throw err;
		}
	},
};
```

```ts
export default {
	async fetch(request): Promise<Response> {
		const controller = new AbortController();

		// Cancel the wait after 500ms
		setTimeout(() => controller.abort(), 500);

		try {
			await scheduler.wait(5000, { signal: controller.signal });
			return new Response("Wait completed");
		} catch (err) {
			if (err instanceof DOMException && err.name === "AbortError") {
				return new Response("Wait was cancelled", { status: 408 });
			}
			throw err;
		}
	},
} satisfies ExportedHandler;
```

## Related resources

* [Timers](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/web-standards/#timers) — `setTimeout()` and `setInterval()` APIs
* [Performance and timers](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/performance/) — `performance.now()` and timer security behavior
* [AbortController and AbortSignal](https://66f4ea29.previews.developers.cloudflare.com/workers/runtime-apis/web-standards/#abortcontroller-and-abortsignal) — cancel asynchronous operations
* [WICG Scheduling APIs proposal ↗](https://github.com/WICG/scheduling-apis) — the specification this API is based on

Was this helpful?

YesNo

## On this page

[![](https://66f4ea29.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://66f4ea29.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workers/runtime-apis/scheduler/#page","headline":"Scheduler · Cloudflare Workers docs","description":"Use the scheduler.wait() API to delay execution in Workers.","url":"https://developers.cloudflare.com/workers/runtime-apis/scheduler/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-25","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
