Runtime Backends
The Waxell Runtime uses pluggable backends for different deployment scenarios. This enables the same code to run locally and in production.
Backend Protocols
| Protocol | Default (Runtime) | Production (Infra) |
|---|---|---|
TokenSemaphore | InMemoryTokenSemaphore | RedisTokenSemaphore |
TaskStatusProvider | InMemoryTaskStatusProvider | InMemoryTaskStatusProvider |
RuntimeBackend | InMemoryBackend | DjangoRuntimeBackend |
GovernanceHook | (none) | PolicyGovernanceHook |
Local Development
In local development, defaults are used automatically:
from waxell_runtime import RuntimeConfig
# Uses in-memory implementations
config = RuntimeConfig.get()
No Redis, Celery, or Django required for local development.
Production Configuration
Production backends are configured by the waxell-infra Django app:
# settings.py
INSTALLED_APPS = [
...
'waxell_infra', # Automatically configures runtime backends
]
The infra app's ready() hook configures:
RedisTokenSemaphorefor rate limitingInMemoryTaskStatusProviderfor async task trackingDjangoRuntimeBackendfor persistencePolicyGovernanceHookfor policy enforcement
Custom Backends
You can implement custom backends by following the protocols:
from waxell_runtime import TokenSemaphore
class MyTokenSemaphore:
"""Custom concurrency backend.
TokenSemaphore is a runtime_checkable Protocol — implement these three
methods and pass an instance to RuntimeConfig.configure(). All three are
SYNCHRONOUS; the runtime calls them from its own scheduling path.
"""
def try_acquire(self, queue: str) -> bool:
"""Atomically take a token. False when none are available."""
...
def release(self, queue: str) -> None:
"""Give a token back."""
...
def set_capacity(self, queue: str, count: int) -> None:
"""Set max concurrent tokens for a queue."""
...
Next Steps
- Production Guide - Deploy with production backends
- Architecture Guide - Understand the full system