Skip to main content
Restate services support several configuration options to adapt their behavior for different use cases. These include timeout settings, retry policies, retention policies, and privacy controls.

Retries

Restate retries failed invocations according to a retry policy. The retry policy always uses exponential back-off. You can tune the initial interval, the exponentiation factor and the maximum interval. The retry policy can set the maximum number of attempts, which can be either limited or unlimited. When attempts are exhausted, you can configure what Restate should do with the invocation:
  • Pause it, requiring the user to manually resume it.
  • Kill it, which automatically fails the invocation and responds to the caller with a terminal error. Note: compensation logic will not be executed, so this may leave your service in an inconsistent state. For more details, check killing the invocation.
Default: Unlimited retries with exponential policy up to 10 seconds of interval (tunable in self-hosted Restate as default-retry-policy) When to adjust: To bound the maximum number of attempts when running on FaaS, avoiding costs for unnecessary retries. For example, when an invocation constantly fails on the same bug. Use longer retry intervals when you want to reduce the load on downstream services, or shorter intervals when you want snappier retries.

Retention of completed invocations

You can tune the retention period of the metadata and journal of completed invocations. Decrease the retention period to save disk space. Increase it to preserve a longer history of your invocations.
How long Restate retains idempotency keys to prevent duplicate request processing.You can see the status of the completed invocation in the UI.Default: 24 hoursWhen to adjust: For services that need longer idempotency windows, such as financial transactions or critical business operations.
The workflow retention describes for how long you will be able to call the shared handlers on a workflow after the run handler has finished. The retention time starts counting down from the moment the run handler completes.After this time, the workflow’s K/V state is cleared, you cannot call any shared handlers anymore, and any Durable Promises are discarded.Default: 24 hoursWhen to adjust: For workflows that need longer retention windows, to retrieve state or the result of a Durable Promise.
How long Restate keeps invocation journals after completion for debugging and auditing.Increase to see journals of completed invocations in the log.For workflow executions or invocations with idempotency keys:
  • the journal retention is capped by the workflow retention or idempotency retention time
  • If the journal retention is set to 0, you can see completion status but not journal entries.
Default: 24 hours (tunable in self-hosted Restate as default-journal-retention)When to adjust: For workflows, AI agents, or any service where you need to inspect the execution history after completion.

Timeouts

There are two types of timeouts describing the behavior between Restate and the service deployment. You should tune these values if you have long-running operations in your code.
The maximum time Restate waits for new journal entries from a service before Restate considers it stalled. After this timeout, Restate will ask the service to suspend.Default: 1 minute (tunable in self-hosted Restate as worker.invoker.inactivity-timeout)When to adjust: For long-running operations like LLM calls, long-running tasks, or external API calls that take longer than the default timeout.
Once the inactivity timeout is reached, Restate will wait for the abort timeout before interrupting the user code. So this is the maximum time Restate will wait for a service to suspend before it forcibly aborts the execution.Default: 1 minute (tunable in self-hosted Restate as worker.invoker.abort-timeout)When to adjust: For long-running operations like LLM calls, long-running tasks, or external API calls that take longer than the default timeout.

Private services

Services can receive requests from HTTP, Kafka and via other services. You can mark services as private to prevent receiving requests from HTTP and Kafka, while allowing internal service-to-service communication. Default: Public When to adjust: When you want to forbid requests from 3rd party services through the Restate HTTP API, e.g. for an internal utility service that shouldn’t be exposed externally, or for a backend service that only other Restate services should access.

State

Virtual Objects and Workflow allow to store persistent state. You can tune the state access behavior in your services and handlers.
To access the Virtual object/Workflow embedded K/V store, there are two strategies:
  • Eager: A full snapshot of all K/V entries of the invoked Virtual Object/Workflow instance is sent when an invocation is invoked.
  • Lazy: Each K/V entry is individually loaded when read through ctx.get. On Lambda and other FaaS platforms that doesn’t support bidirectional streaming, this requires the invocation to suspend and replay.
Default: EagerWhen to adjust: Enable lazy state when you have potentially large state entries, but your handler doesn’t get all of them. Enable eager state if your state is small, or you’re on AWS Lambda and the cost of replay is too high.

How to configure

Service-level configuration

To configure your services:
// Add service options to the service definition
const myWorkflow = restate.workflow({
  name: "MyWorkflow",
  handlers: {
    run: async (ctx: restate.Context) => {},
  },
  options: {
    retryPolicy: {
      initialInterval: { seconds: 1 },
      maxInterval: { seconds: 30 },
      maxAttempts: 10,
      onMaxAttempts: "pause",
    },
    abortTimeout: { minutes: 15 },
    inactivityTimeout: { minutes: 15 },
    idempotencyRetention: { days: 3 },
    workflowRetention: { days: 3 }, // only for workflows
    journalRetention: { days: 7 },
    ingressPrivate: true,
    enableLazyState: true, // only for Virtual Objects and Workflows
  },
});

Handler-level configuration

To set configuration at the handler level:
// Add handler options to the handler definition
// For services:
const myService = restate.service({
  name: "MyService",
  handlers: {
    myHandler: restate.handlers.handler(
      {
        retryPolicy: {
          initialInterval: { seconds: 1 },
          maxInterval: { seconds: 30 },
          maxAttempts: 10,
          onMaxAttempts: "pause",
        },
        abortTimeout: { minutes: 15 },
        inactivityTimeout: { minutes: 15 },
        idempotencyRetention: { days: 3 },
        journalRetention: { days: 7 },
        ingressPrivate: true,
      },
      async (ctx: restate.Context) => {}
    ),
  },
});

// For Virtual Objects:
const myObject = restate.object({
  name: "MyObject",
  handlers: {
    myHandler: restate.handlers.object.exclusive(
      {
        retryPolicy: {
          initialInterval: { seconds: 1 },
          maxInterval: { seconds: 30 },
          maxAttempts: 10,
          onMaxAttempts: "pause",
        },
        abortTimeout: { minutes: 15 },
        inactivityTimeout: { minutes: 15 },
        idempotencyRetention: { days: 3 },
        journalRetention: { days: 7 },
        ingressPrivate: true,
        enableLazyState: true,
      },
      async (ctx: restate.ObjectContext) => {}
    ),
    mySharedHandler: restate.handlers.object.shared(
      {
        /*... my options ...*/
      },
      async (ctx: restate.ObjectSharedContext) => {}
    ),
  },
});

// For Workflows:
const myWf = restate.workflow({
  name: "MyWf",
  handlers: {
    run: restate.handlers.workflow.workflow(
      {
        retryPolicy: {
          initialInterval: { seconds: 1 },
          maxInterval: { seconds: 30 },
          maxAttempts: 10,
          onMaxAttempts: "pause",
        },
        abortTimeout: { minutes: 15 },
        inactivityTimeout: { minutes: 15 },
        journalRetention: { days: 7 },
        ingressPrivate: true,
        enableLazyState: true,
      },
      async (ctx: restate.WorkflowContext) => {}
    ),
    signal: restate.handlers.workflow.shared(
      {
        /*... my options ...*/
      },
      async (ctx: restate.WorkflowSharedContext) => {}
    ),
  },
});

Override configuration

You can override the service options configured in your code via the UI or CLI. These options apply until the next revision of the service is registered.
Use the Restate UI to configure services interactively:
  • Navigate to your registered deployment
  • Click on the service you want to configure
  • Modify settings through the web interface
Use the Restate CLI to edit the configuration:
restate services config edit <SERVICE_NAME>
I