[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Schedule](https://evolu.dev/docs/api-reference/common/Schedule) › Schedule

```ts
type Schedule<Output, Input> = (
  deps: ScheduleDeps,
) => (input: Input) => NextResult<readonly [Output, Millis]>;
```

Defined in: [packages/common/src/Schedule.ts:111](https://github.com/evoluhq/evolu/blob/037c390af081e9944d616ff298a729515c5c5ab7/packages/common/src/Schedule.ts#L111)

Composable scheduling strategies for [retry](https://evolu.dev/docs/api-reference/common/Task/functions/retry), [repeat](https://evolu.dev/docs/api-reference/common/Task/functions/repeat), rate
limiting, and more.

A Schedule uses the State pattern: calling `schedule(deps)` creates a step
function with internal state captured in closures. Each call to `step(input)`
advances that state and returns `Ok([Output, Millis])` or `Err(Done<void>)`
to stop. Multiple calls to `schedule(deps)` create independent state
instances.

`Err(Done<void>)` is terminal. After a step returns it, every subsequent call
to that step must also return `Err(Done<void>)`.

With [retry](https://evolu.dev/docs/api-reference/common/Task/functions/retry) and [repeat](https://evolu.dev/docs/api-reference/common/Task/functions/repeat), the initial Task execution happens
before the first schedule step. Schedule outputs therefore describe
recurrences, not the initial execution. Time-based schedules establish their
time origin on the first step call, not when `schedule(deps)` creates the
step.

### Composing a retry policy

```ts
import {
  assertOk,
  err,
  exponential,
  jitter,
  maxDelay,
  ok,
  retry,
  take,
  testCreateRun,
  type RandomNumber,
  type Task,
} from "@evolu/common";

let attempts = 0;
const fetchData: Task<string, { readonly type: "FetchError" }> = () => {
  attempts++;
  return attempts < 2 ? err({ type: "FetchError" }) : ok("data");
};

const fetchWithRetry = retry(
  fetchData,
  // A jittered, capped, limited exponential backoff.
  jitter("100%")(maxDelay("20s")(take(2)(exponential("100ms")))),
);

await using run = testCreateRun({
  random: { next: () => 0 as RandomNumber },
});
assertOk(await run(fetchWithRetry), "data");
```

Or use a preset:

```ts
import {
  assertTrue,
  ok,
  retry,
  retryStrategyAws,
  type Task,
} from "@evolu/common";

const fetchData: Task<string> = () => ok("data");
const fetchWithRetry = retry(fetchData, retryStrategyAws);

assertTrue(typeof fetchWithRetry === "function");
```