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
Metadata
Release files for durable-monty 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| durable_monty-0.1.5.tar.gz | 62.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| durable_monty-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.6 kB
Release files / durable_monty-0.1.5.tar.gz
| Download URL | durable_monty-0.1.5.tar.gz |
|---|---|
| Size | 62.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
91146072fcbaa0b83362d1a447786b60e701e7aabb8307df252dbad4f00dd805
|
|
BLAKE2b-256 checksum How to use checksums |
ab4091864c4ab3d926052d5f613cdf65b7dd497c554e067da3abb837c14c946a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 10, 2026.
Transparency logRelease files / durable_monty-0.1.5-py3-none-any.whl
| Download URL | durable_monty-0.1.5-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
63df22cdd98a8e9602383e934e52ed3f09cc1263b437cae827b83a131f49ec5e
|
|
BLAKE2b-256 checksum How to use checksums |
40bb2aad0c46e2e520ed8dc59c917f6331fe4494763c3cb6dd4aae169b5c9208
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 10, 2026.
Transparency log