Code owns behavior
Use branches, libraries, and models without forcing application logic into a graph of operators.
Highwater keeps each key ordered and recovers accepted events, state, and output after failures—with event-time progress built in.
One Process per business key. No topology builder. Highwater recovers accepted events and Process state.
@process.defn(key="account_id")
@dataclass
class Balance:
total: int = 0
@process.event
async def apply(self, event):
self.total += event.amount
return {
"balance": self.total
}
The programming model
A Process is one durable state machine for every account, device, user, or order. Events for one key stay ordered. Different keys run independently.
Use branches, libraries, and models without forcing application logic into a graph of operators.
Accepted events, state transitions, timers, and output recover together after execution failures.
One key stays consistent while unrelated keys can make progress concurrently.
Event-time progress
Late events are normal. A Process can wait until configured source progress indicates that no earlier on-time event is expected, then resume ordinary application code.
Created at 10:02, paid at 10:06, and an address update for 10:04 arrived late. Source progress is complete through 10:12, so the event-time gate is open.
await process.wait_until(
process.event_time >= ship_at
)
gate open
Adaptive batching
Vectorize model inference under load. When traffic is sparse, Highwater flushes before the oldest event exceeds its latency budget.
A precise failure contract
Highwater protects the event and every state transition it causes.
An event is accepted only after its identity and payload are durably recorded.
One key commits one transition at a time, even when an invocation is retried.
Process state and Highwater output become visible in the same commit.
Mailboxes, timers, event-time progress, and operator state recover together.
Application code may run more than once after failure. Fenced completions prevent stale attempts from committing; external APIs should use a stable idempotency key.
Built for application logic
Use native streaming state where it helps. Keep the logic that makes your product different in code.
Join live behavior with the version of product data valid when the event occurred.
Track per-device state, close event-time windows, and respond to meaningful conditions.
Apply authorizations, reversals, and policy changes in consistent per-account order.
Batch embeddings or predictions by size and latency without turning off the stream.
Early access
Join the early-access list for product updates, design partnerships, and the first hosted deployments.