Durable functions using monty-python
Project description
Durable Monty
⚠️ Experimental: This is an experimental project exploring a different approach to durable functions. Not recommended for production use yet.
Durable functions for Python. Write normal async/await code that pauses at gather(), executes tasks in parallel (even distributed), and resumes when done.
What Are Durable Functions?
Durable functions are workflows that survive crashes and restarts. Your code pauses when waiting for tasks, saves its state to a database, and resumes exactly where it left off when tasks complete - even if your process dies in between.
Perfect for: Long-running workflows, parallel task execution, distributed systems, background jobs.
How It Works
Powered by monty-python - a sandboxed Python interpreter that can pause and serialize execution state. When your code hits await gather(), Monty captures the exact execution state (~800 bytes), returns pending tasks, and later resumes from that exact point with results.
Result: Pure Python async/await that works like Temporal or AWS Step Functions, but simpler.
Why This Approach Is Simpler
Other frameworks (Temporal, Durable Functions, etc.):
- Re-execute your entire function from the start on every resume
- Use replay/event sourcing to return cached results for completed calls
- Example: If your workflow pauses at step 7, resuming re-runs steps 1-6 (with cached results) before continuing
- Requires deterministic code and careful side-effect management
Durable Monty:
- Serializes the exact Python execution state (call stack, variables, everything)
- No re-execution - just deserialize and continue from where you left off
- True pause/resume - no replay, no determinism requirements, no special coding patterns
- Simpler mental model: "save and restore" instead of "replay and cache"
Trade-offs:
- Code versioning: Changing workflow code can break in-flight executions (serialized state expects compatible code)
- Migration complexity: Updating workflows requires careful handling of existing executions
- Less proven: Built on pydantic-monty, which is newer than battle-tested frameworks like Temporal
- Python-only: Requires deep interpreter integration, unlike replay-based systems that work with any language
The main practical challenge: if you iterate quickly on workflow code, in-flight executions may break on deployment. Consider draining executions before code changes or using versioned workflows.
from durable_monty import init_db, OrchestratorService, Worker, LocalExecutor
def process(item):
return f"processed_{item}"
code = """
from asyncio import gather
results = await gather(
process('a'),
process('b'),
process('c')
)
results
"""
service = OrchestratorService(init_db())
# Pass function object - full path derived automatically
exec_id = service.start_execution(code, [process])
# Process until complete
worker = Worker(service, LocalExecutor())
worker.run(until_complete=True)
# Get the result
output = service.get_result(exec_id)
print(output) # ['processed_a', 'processed_b', 'processed_c']
Install
uv add durable-monty
How It Works
- Code hits
gather()→ pauses and saves state (~800 bytes) - Creates pending calls in database
- Worker picks them up and executes in parallel
- When all complete → resumes and returns result
State survives restarts. Parallel execution. Pure Python.
Distributed Execution
Redis Queue:
uv add durable-monty --extra rq
from durable_monty.executors.rq import RQExecutor
worker = Worker(service, RQExecutor())
worker.run()
# Start RQ workers: rq worker durable-monty
Event-driven (Lambda, Modal):
uv add durable-monty --extra api
from durable_monty.api import create_app
import uvicorn
app = create_app(service)
uvicorn.run(app, port=8000)
# Executors POST results to: /webhook/complete
Examples
examples/with_worker.py- Local executionexamples/with_rq.py- Redis Queueexamples/with_webhook.py- Webhooks
Development
git clone https://github.com/koenvo/monty-durable
cd monty-durable
uv sync
uv run pytest
License
MIT
Project details
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 durable_monty-0.1.5.tar.gz.
File metadata
- Download URL: durable_monty-0.1.5.tar.gz
- Upload date:
- Size: 62.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91146072fcbaa0b83362d1a447786b60e701e7aabb8307df252dbad4f00dd805
|
|
| MD5 |
8584238765c15003cfa24e17dd7bbfde
|
|
| BLAKE2b-256 |
ab4091864c4ab3d926052d5f613cdf65b7dd497c554e067da3abb837c14c946a
|
Provenance
The following attestation bundles were made for durable_monty-0.1.5.tar.gz:
Publisher:
release.yml on koenvo/durable-monty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
durable_monty-0.1.5.tar.gz -
Subject digest:
91146072fcbaa0b83362d1a447786b60e701e7aabb8307df252dbad4f00dd805 - Sigstore transparency entry: 937471492
- Sigstore integration time:
-
Permalink:
koenvo/durable-monty@d10cb8dde34b876e5b2f1fa76cb5c2f69ac34295 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/koenvo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d10cb8dde34b876e5b2f1fa76cb5c2f69ac34295 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file durable_monty-0.1.5-py3-none-any.whl.
File metadata
- Download URL: durable_monty-0.1.5-py3-none-any.whl
- Upload date:
- Size: 15.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63df22cdd98a8e9602383e934e52ed3f09cc1263b437cae827b83a131f49ec5e
|
|
| MD5 |
3bf8ef25d899808bfd6c9a256d9ae3a3
|
|
| BLAKE2b-256 |
40bb2aad0c46e2e520ed8dc59c917f6331fe4494763c3cb6dd4aae169b5c9208
|
Provenance
The following attestation bundles were made for durable_monty-0.1.5-py3-none-any.whl:
Publisher:
release.yml on koenvo/durable-monty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
durable_monty-0.1.5-py3-none-any.whl -
Subject digest:
63df22cdd98a8e9602383e934e52ed3f09cc1263b437cae827b83a131f49ec5e - Sigstore transparency entry: 937471534
- Sigstore integration time:
-
Permalink:
koenvo/durable-monty@d10cb8dde34b876e5b2f1fa76cb5c2f69ac34295 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/koenvo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d10cb8dde34b876e5b2f1fa76cb5c2f69ac34295 -
Trigger Event:
workflow_dispatch
-
Statement type: