v2.9.0
Restate Java/Kotlin SDK 2.9.0
New API is now the default; codegen API deprecated
The codegen API based on the sdk-api-gen annotation processor / sdk-api-kotlin-gen KSP generator is now deprecated and will be removed in a future release.
Prefer the new API: no annotation processor, handlers drop the Context parameter for the static dev.restate.sdk.Restate methods (Java) or the top-level functions in dev.restate.sdk.kotlin (Kotlin).
Annotations remain the same (@Service, @Handler, …), so migrating is mostly removing the Context parameter and changing how you invoke other services.
The two styles coexist, so you can migrate one service at a time.
// Before (codegen API)
@Handler
public void add(ObjectContext ctx, long value) {
long current = ctx.get(TOTAL).orElse(0L);
ctx.set(TOTAL, current + value);
}
// After (new API)
@Handler
public void add(long value) {
var state = Restate.state();
long current = state.get(TOTAL).orElse(0L);
state.set(TOTAL, current + value);
}See the Migration guide for the full Context API → new API mapping and step-by-step instructions for both Java and Kotlin.
Native core (JDK 23+)
On JDK >= 23 the SDK now runs its core logic, referred as "protocol state machine", through the native shared-core library via Panama/FFM, providing all the latest Restate features to the Java SDK.
- If you run on JDK >= 23, no action is required to use the new core.
- If you run on JDK < 23, the SDK falls back to a pure-Java state machine, which is deprecated. In that case, we suggest upgrading to JDK >= 25.
Check https://github.com/restatedev/sdk-java/tree/main#native-access-on-jdk-23 for more details.
(Preview) Scope and limit key to enable flow control
This release adds the SDK API for flow control, the new Restate 1.7 feature to cap how many invocations run concurrently within a scope, with optional hierarchical limit keys.
Use it to bound cost (especially for AI agents, where every concurrent invocation is real model/API spend), shield downstream systems from bursts, and share capacity fairly across tenants.
To use scope and limit keys in service to service communication:
// Route a call into a named scope
Restate.scope("tenant-123").service(MyService.class).process(payload);
// Add a limit key for hierarchical concurrency limits within the scope
Restate.scope("tenant-123").workflowHandle(MyWorkflow.class, "wf-key")
.call(MyWorkflow::run, input, InvocationOptions.limitKey("api-key/user42").build())
.await();The same API is available on the ingress Client (client.scope("tenant-123").service(MyService.class)).
Check out the Flow control documentation for more details on how concurrency limits work and how to set them up.
NOTE: This API is in preview and is not enabled by default. To use it in restate-server 1.7, enable the flow control and protocol v7 experimental features via
RESTATE_EXPERIMENTAL_ENABLE_PROTOCOL_V7=trueandRESTATE_EXPERIMENTAL_ENABLE_VQUEUES=true(new clusters only). See https://docs.restate.dev/services/flow-control for details.
Signals API
Signals let invocations communicate directly with each other: one invocation waits for a signal, and any other handler can resolve or reject it by referencing the target invocation's ID.
// Inside the invocation that wants to wait:
boolean approved = Restate.signal("approved", Boolean.class).await();
// Inside another handler that knows the target invocation's ID:
InvocationHandle<?> target = Restate.invocationHandle(targetInvocationId);
target.signal("approved").resolve(Boolean.class, true);
// or, to wake the waiter with a terminal error:
target.signal("approved").reject("Request denied");Restate.invocationHandle(invocationId) returns an InvocationHandle, which you can also use to cancel() the target invocation or attach() to wait for its result.
Other changes
- Configurable, multi-event-loop HTTP server, enabled by default. The Vert.x HTTP server now runs on multiple event loops out of the box. Configure it in Spring via
restate.sdk.http.eventLoops, or in the vanilla SDK via theRESTATE_SDK_HTTP_EVENT_LOOPSenv variable /dev.restate.sdk.http.eventLoopssystem property. - Generic calls/sends. Added
Restate.call(request)/Restate.send(request[, delay])in Java andprepareRequest(request).call()/prepareRequest(request).send(delay)in Kotlin, for invoking services from a rawRequest. - Admin client deprecated. The admin client is now deprecated.
- Vert.x 5 compatibility. Fixed a compatibility issue with Vert.x 5.
- JSON schema
$refbugfix.DefaultJsonSchemaFactoryno longer replaces a nested type name when it merely shares the prefix of the root class name (e.g.Task&TaskType), which previously produced an unserializable schema that crashed at runtime. - Dependency bumps. Minimum Jackson version bumped (along with AssertJ and Kotlin); Kotlin and KSP bumped to 2.3.0.
New Contributors
Full Changelog: v2.8.0...v2.9.0