Skip to main content
The Restate Java/Kotlin SDK is open source and available on GitHub. The Restate SDK lets you implement handlers. Handlers can be part of a Basic Service, a Virtual Object, or a Workflow. This page shows how to define them with the Java/Kotlin SDK.

Prerequisites

  • JDK >= 17 (JDK >= 23 recommended, required for the latest Restate features)

Getting started

Get started quickly with the Java or Kotlin Quickstart.
To start building Restate services, add the SDK dependency to your Maven/Gradle project manifest. The SDK comes in different flavors: Java or Kotlin API, HTTP or Lambda. Choose the one you need depending on the language you want to use and whether you want to deploy the service as an HTTP server or as AWS Lambda.
The SDK uses a native library on JDK 23+. To silence the native-access warning printed at startup, enable native access by passing --enable-native-access=ALL-UNNAMED as a JVM argument, or by setting Enable-Native-Access: ALL-UNNAMED in your JAR manifest.
The SDK creates proxies for your services, which requires non-final classes. Kotlin classes are final by default, so apply the Kotlin all-open compiler plugin for the Restate annotations. The Spring Boot Kotlin starter applies this automatically; for a plain Gradle project add:
Kotlin/Gradle
Alternatively, use on each Restate annotated class open.
Using Spring Boot? See Spring Boot for the starter dependency, @RestateComponent, dependency injection, and injecting the ingress Client.

Basic Services

Basic Services group related handlers and expose them as callable endpoints:
  • Define a service using the @Service and @Handler annotations
  • Each handler can be called at <RESTATE_INGRESS>/MyService/myHandler. To override the service name (default is simple class name), use the annotation @Name.
  • Access Restate’s capabilities (state, calls, side effects, timers, …) through the static methods on the Restate class (Java), or the top-level functions in the dev.restate.sdk.kotlin package (Kotlin).
  • The input parameter (at most one) and return type are optional and can be of any type. See serialization for more details.
  • Create an endpoint to expose the service over HTTP (port 9080 by default).

Virtual Objects

Virtual Objects are services that are stateful and key-addressable — each object instance has a unique ID and persistent state.
  • Use the @VirtualObject annotation.
  • Each instance is identified by a key, accessible via Restate.key() (Java) or objectKey() (Kotlin).
  • Access the object’s persistent state via Restate.state() (Java) or state() (Kotlin).
  • Virtual Objects can have exclusive and shared handlers.
  • Exclusive handlers (the default) have read/write access to the object state.
  • Shared handlers use the @Shared annotation and have read-only access to the state.

Workflows

Workflows are long-lived processes with a defined lifecycle. They run once per key and are ideal for orchestrating multi-step operations, which require external interaction via signals and queries.
  • Create the workflow by using the @Workflow annotation.
  • Every workflow must include a run handler:
    • This is the main orchestration entry point
    • It runs exactly once per workflow execution
    • Resubmission of the same workflow will fail with “Previously accepted”. The invocation ID can be found in the request header x-restate-id.
    • Use Restate.key() (Java) or workflowKey() (Kotlin) to access the workflow’s unique ID
  • Additional handlers use the @Shared annotation and can signal or query the workflow. They can run concurrently with the run handler and until the retention time expires.

Configuring services

Check out the service configuration docs to learn how to configure service behavior, including timeouts and retention policies.