Highwater
Durable execution for streaming applications.
Highwater lets you write stateful stream processing as ordinary Python. It keeps each key ordered, persists every accepted event and state transition, tracks event-time progress, retries failed invocations, and scales execution with load.
from dataclasses import dataclass
from highwater import process
@dataclass(frozen=True)
class Deposit:
account_id: str
amount: int
@process.defn(key="account_id")
@dataclass
class Balance:
total: int = 0
@process.event
async def apply(self, event: Deposit):
self.total += event.amount
return {"account_id": event.account_id, "balance": self.total}
No topology builder. No separate state database. No recovery code in your application.
Install Highwater
pip install highwater
Run locally
highwater dev app.py
highwater dev starts a complete local environment, discovers the Processes in app.py, and prints the local ingestion endpoint. Storage, partitions, leases, and execution pools use development defaults.
Send an event from Python:
from highwater import Client
client = Client()
balances = client.process("Balance")
await balances.send(
Deposit("account-a", 5),
event_id="deposit-1001",
)
Or send JSON to the generated event endpoint:
curl -X POST http://localhost:7233/v1/processes/Balance/events \
-H 'content-type: application/json' \
-H 'idempotency-key: deposit-1001' \
-d '{"account_id":"account-a","amount":5}'
Deploy
highwater deploy app.py
Highwater packages the application, creates a versioned deployment, provisions event ingestion, and scales execution independently for each state partition. The same Process API runs continuously, on demand, or on a schedule.
highwater deploy app.py --schedule '0 * * * *'
A schedule controls when compute drains available events. It does not turn off ingestion or weaken durability.
Why Highwater
Traditional stream processors are good at dataflow graphs. Durable execution systems are good at long-running application code. Highwater combines their strongest ideas around one abstraction: a durable Process keyed by the entity your application already understands.
events ──► durable inbox ──► Python Process ──► state + output
per key retryable atomic
- One key runs one state transition at a time.
- Different keys scale independently.
- Accepted events survive executor and host failures.
- State and output commit together.
- Stable event identifiers make uncertain retries safe.
- Watermarks let code wait for event-time completeness.
- Backpressure reaches ingestion before queues become unbounded.
Streaming that can be batchy
Highwater continuously batches transport and durable commits. Application code stays event-oriented unless it opts into vectorized execution:
@process.defn(key="document_id")
class Embeddings:
@process.batch(max_size=128, max_delay=0.025)
async def embed(self, documents: list[Document]):
vectors = await model.embed([doc.text for doc in documents])
return [
{"document_id": doc.document_id, "embedding": vector}
for doc, vector in zip(documents, vectors, strict=True)
]
The batch runs when it reaches 128 documents or its oldest document waits 25 milliseconds. Scheduled deployments use the same mechanism to drain finite bursts and scale back to zero.
Event time without a dataflow language
@process.defn(
key="account_id",
event_time="occurred_at",
wait_until=process.complete,
)
@dataclass
class DailyBalance:
total: int = 0
process.complete runs an event only after Highwater knows the input is complete through that timestamp. The platform owns source progress, idleness, late-data policy, and watermark coordination.
Highwater also provides native incremental filters, windows, deduplication, interval joins, and temporal as-of joins. Use them for common state machines and keep application-specific decisions in Python.
Event ingestion
Every deployment receives managed HTTPS and SDK ingestion. Highwater assigns durable source positions, validates idempotency keys, partitions by Process key, and applies admission backpressure.
Customers publish events to Highwater. Connectors, brokers, storage tiers, and partition movement are platform concerns rather than application configuration.
Execution model
Highwater groups keyed Processes into movable partitions. Each partition pipelines and group-commits state transitions, keeps hot state close to execution, and snapshots durable progress asynchronously. Execution containers are cached according to observed traffic and can scale to zero when idle.
Cross-partition messages carry causal commit dependencies. A receiver can begin speculative work, but it cannot commit a result before the sender's dependency is durable. This avoids a distributed transaction on every message while preserving recovery order.
Leases control where an invocation may run. A lease token is a renewable capability tied to a durable partition generation. Expiration only makes a lease eligible for revocation; a durable generation change fences the old executor. Late completions from a prior generation cannot commit.
These choices follow the partitioned, pipelined execution model described by Microsoft Research's Netherite and the workload-aware warm execution findings from Serverless in the Wild.
Delivery guarantees
| Boundary | Guarantee |
|---|---|
| Event admission | acknowledged after a durable append |
| Per-key execution | ordered, one committed transition at a time |
| Invocation | at least once across failures |
| State and output | atomic within one Process transition |
| Event retry | idempotent with a stable event identifier |
| Output delivery | at least once with a stable message identifier |
| Event-time progress | monotonic per input partition |
Direct, non-idempotent external side effects can still occur more than once when an invocation fails after the effect. Use a destination idempotency key or Highwater's transactional output delivery.
Performance
The partition execution path completes 100,000 distinct durable keyed transitions at a median 99,951 events per second with five execution instances on one development machine. The ordinary per-event handler reaches a median 89,029 events per second. Every admission and completion is acknowledged only after its authoritative WAL append.
Execution instances receive disjoint partition sets, so application compute can run on separate hosts without coordinating each event. Durable owner epochs and activation sequences fence delayed work after a service restart. Moving the partition state-machine owners themselves between service hosts remains part of the multi-host durability work described in Scaling architecture.
See Performance for the reproducible benchmark, scaling results, and measurement boundary. One hot key remains serial by design; split the key or use a commutative aggregation when one entity needs internal parallelism.
Documentation
The Docusaurus site lives in website.
cd website
yarn install
yarn start
The public documentation covers durable Processes, managed event ingestion, event time, batching, scheduled deployments, joins, scaling, backpressure, upgrades, recovery, delivery guarantees, and lease fencing.
The standalone product landing page lives in landing. Its static files can be previewed directly and deployed to an S3 origin without an application server.
Repository
The repository contains the execution engine, Python SDK, examples, benchmarks, and documentation source. Internal crate and module names remain implementation details behind the packaged CLI.
crates/ execution and protocol implementation
src/temporal_code/ Python SDK implementation
examples/ streaming applications
benchmarks/ durable throughput benchmark
docs/ implementation design notes
website/ public documentation
landing/ product landing page
Build the implementation
Contributors working on the engine can build and test from source. End users install highwater and use highwater dev; these commands are not part of the customer setup path.
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
PYTHONPATH=src python3 -m unittest discover -s tests -v
cd website && yarn build
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file highwater-0.0.1.tar.gz.
File metadata
- Download URL: highwater-0.0.1.tar.gz
- Upload date:
- Size: 28.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1402fac8bb22bde4d83f59898aeb27925c3df4ceb78503344cb9ee7ca7d16e4
|
|
| MD5 |
8cdfc52dbd8c9f060d9227d37454f08f
|
|
| BLAKE2b-256 |
aadf77c276636f32f490661f3a40298998e162e340218cba9e2aa3b0cc28fe67
|
Provenance
The following attestation bundles were made for highwater-0.0.1.tar.gz:
Publisher:
publish-pypi.yml on henneberger/highwater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
highwater-0.0.1.tar.gz -
Subject digest:
c1402fac8bb22bde4d83f59898aeb27925c3df4ceb78503344cb9ee7ca7d16e4 - Sigstore transparency entry: 2681297301
- Sigstore integration time:
-
Permalink:
henneberger/highwater@813b50376bddcb992c19ec4e85fcf0978a7c1ced -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/henneberger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@813b50376bddcb992c19ec4e85fcf0978a7c1ced -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file highwater-0.0.1-py3-none-any.whl.
File metadata
- Download URL: highwater-0.0.1-py3-none-any.whl
- Upload date:
- Size: 29.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d698a2f32d21f80e0f66b054d9f0d06da43b93df1da2734e811b9a08372f9e4f
|
|
| MD5 |
ae89cc411fa77631169a221e6d72e564
|
|
| BLAKE2b-256 |
29ca59abc3cba723b3df8bc2a945dab461f5cf8497032c7e629e3fe9e78c2c41
|
Provenance
The following attestation bundles were made for highwater-0.0.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on henneberger/highwater
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
highwater-0.0.1-py3-none-any.whl -
Subject digest:
d698a2f32d21f80e0f66b054d9f0d06da43b93df1da2734e811b9a08372f9e4f - Sigstore transparency entry: 2681297352
- Sigstore integration time:
-
Permalink:
henneberger/highwater@813b50376bddcb992c19ec4e85fcf0978a7c1ced -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/henneberger
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@813b50376bddcb992c19ec4e85fcf0978a7c1ced -
Trigger Event:
workflow_dispatch
-
Statement type: