Restate 1.7: End-to-end Flow Control for your Agents and Backends | Restate
4.1k
Cloud Login
BlogRestate 1.7: End-to-end Flow Control for your Agents and Backends<br>July 7, 2026<br>Restate Team<br>Today we're releasing Restate 1.7 , which marks the biggest release since we introduced distributed Restate last year. The marquee feature of this release is sophisticated Flow Control , powered by Virtual Queues (vqueues). To make that happen, we completely re-built Restate's internal scheduler architecture.
This change gives Restate the ability to steer load across your infrastructure , your agents and applications, in a way both simpler and more sophisticated than message queues. Together with Restate's existing capabilities for durable execution, stateful functions (virtual objects), and reliable RPC/messaging, it forms a durable foundation for your backends and agents that goes much beyond traditional durable execution . All of that, while keeping Restate as a dependency-less single binary, preserving the lightweight experience and flexible deployments Restate is known for.
Let's dive deeper into this.
The magic of declarative flow control
Flow Control controls how fast, or with which priorities, events and invocations are dispatched to your services and agents.<br>For backend- or agent platforms, this means controlling which agents get to execute next when there is limited capacity, what tool may access a constrained database next, or how many inference calls a team is at most allowed to do in a certain time frame.
Virtual Queues allow you to define and control this on a very fine-grained basis, like a team, user, or an agent. In the Restate APIs, you assign an invocation to a scope (representing, e.g., team or user) and that determines the virtual queue. Invocations share limits with all other invocations assigned to the same scope (queue). Like Virtual Objects, the virtual nature of vqueues means you can have millions or more of them.
Try it out: requests keep arriving into Restate, where each scope has its own queue. Hollow dots wait in the queue; filled dots hold a concurrency slot in the custom LLM gateway. Toggle the rules off to see what happens when unprotected traffic overloads the gateway.
Limits are defined through flexible rules. What is unique in Restate's vqueues is that you can structure limits hierarchically . For example, you can define that a scope (organization) gets max 1000 concurrent invocations (e.g. agent runs), each team for that org gets max 100 and each user in the team max 10. All limits need to be met for a workflow to run. A rule can be set to apply for any tenant/team/user, or override the limits of a specific team or tenant.
The best part: The rules defining the limits can be dynamically updated via the admin API. So if you temporarily need to give one of your users or teams more capacity, it is one http call away.
restate rules set "*" --concurrency 1000 # each organization<br>restate rules set "sales" --concurrency 500 # sales gets less<br>restate rules set "*/*" --concurrency 100 # each team in any org<br>restate rules set "*/admins" --unlimited # admin teams: no limit (overrules "*/*")<br>restate rules set "*/*/*" --concurrency 10 # each individual user
To apply these limits, you tag an invocation with a scope, and optionally additional hierarchical limits in a limit key. The scope selects the top-level virtual queue; the limit key adds the nested team and user levels:
# "acme" is the scope (org); the limit key adds the team and user levels.<br>curl "localhost:8080/restate/scope/acme/call/Inference/run?limit-key=growth/alice" \<br>--json '{"prompt": "..."}'
# The limit key can also be passed as a header instead of a query parameter.<br>curl localhost:8080/restate/scope/acme/call/Inference/run \<br>-H 'x-restate-limit-key: growth/alice' \<br>--json '{"prompt": "..."}'
From another Restate service, you set the same scope and limit key directly on the SDK call: ctx.scope(...) picks the top-level virtual queue and rpc.opts({ limitKey }) adds the nested levels.
// Route the call into the "acme" scope (org) and attach a hierarchical limit key<br>ctx.scope("acme").serviceClient(Inference)<br>.run(<br>{ prompt: "..." },<br>opts({ limitKey: "growth/alice" })<br>);
End-to-end scheduling
We believe that this type of flow control on the events/invocations that trigger work (like agent turns) is a great way to steer and control load in the infrastructure . Compared to, for example, scheduling policies on the container runtime, the durable execution and queuing system has a richer view, because it naturally sees all the ongoing executions, event backlogs, plus all the conditions that determine whether a durable function (like an agent) can make progress or whether it is waiting on another durable function (e.g., subagent) or an external event (e.g., approval):
Is the team/user/agent within quota? (Restate: virtual queues' rules fulfilled)
Is the agent currently processing a message and the new message should be kept...