Runtime & sandbox
How PyOrchestrator isolates Python scripts: subprocess sandboxes, venv, rlimits, Redis queue, and live logs.
Principle
User scripts do not receive a separate Docker container. All runs are executed as isolated subprocess inside the runtime service.
Runtime Engine
├── Redis BLPOP runtime:jobs
├── SandboxPool (semaphore max_concurrent)
│ └── One sandbox per run
│ ├── venv (per workspace)
│ ├── subprocess python entrypoint
│ ├── RLIMIT_CPU / RLIMIT_AS
│ └── wall-clock timeout
└── POST /internal/runs/* → backend
Run lifecycle
- Queue - backend creates
Run(statusqueued), puts job in Redis - Start - runtime picks up the job, calls
/internal/runs/start - Execution - sandbox runs
entrypointwith secrets in env (SECRET_*) - Logs - stdout/stderr → WebSocket + PostgreSQL
- Completion — exit code, duration →
/internal/runs/complete - Stop - UI publishes
stoptorun:{id}:control, SIGTERM process
Isolation
| Layer | Mechanism |
|---|---|
| Process | subprocess.Popen |
| FS | /workspaces/{script_id}/{run_id}/ |
| Dependencies | pip install -r requirements.txt to local venv |
| CPU/Memory | resource.setrlimit |
| Time | asyncio.wait_for wall timeout |
| Secrets | Encryption at rest, injection at run |
Scaling
docker compose -f docker-compose.prod.yml - several replicas of runtime, a common Redis queue.
Hot code reload
Saving the script in the UI → Redis script:updated → runtime invalidates the venv cache → next run with new code without restarting the containers.