Runway is an open-source service for executing code through a queue-backed service and worker architecture. It is designed for multilingual execution through language-specific workers; the current implementation includes a Python worker.
The repository contains the HTTP service, the Python worker, and the Helm chart used to deploy them together.
service/ Spring Boot WebFlux gateway for the execution API
python-worker/ Python worker that consumes execution jobs from NATS JetStream
charts/runway/ Helm chart for deploying Runway
docs/ Project documentation
examples/ Example requests, deployments, and integrations
The main execution endpoint is:
POST /api/v1/execute
Example request:
{
"snippet": "print('Hello, World!')",
"timeoutMs": 5000,
"stdin": null,
"executionType": "safe"
}Example response:
{
"exitCode": 0,
"stdout": "Hello, World!\n",
"stderr": "",
"executionTimeMs": null
}Batch execution is available at:
POST /api/v1/execute/batch
See service/README.md for the complete HTTP API, service configuration, metrics, and dead letter queue behavior.
Runway separates the public API from code execution. Clients talk to the service over HTTP. The service publishes execution jobs to NATS JetStream — a lightweight, high-performance messaging system with persistent streams — waits for a worker response on a per-request reply subject, and returns the result to the client. NATS JetStream is used as the execution queue: it decouples the HTTP service from workers, provides at-least-once delivery, and allows workers to be scaled independently.
Client
-> Runway service
-> NATS JetStream stream
-> Python worker
<- worker reply
<- HTTP response
The service owns request routing, timeouts, API responses, metrics, and the dead letter queue. Workers own language-specific execution. This keeps the service independent from any one runtime and allows additional worker implementations to be added without changing the HTTP API shape.
The current API executes Python snippets through the Python worker. Requests can be sent one at a time or as batches. The worker supports safe and unsafe execution modes; see python-worker/README.md for the exact behavior and tradeoffs.
For local development from source:
- Docker, for running NATS locally
- JDK 21+, for the service
- Python 3.12+
- uv, for Python dependency management
For Kubernetes deployment:
- A Kubernetes cluster
kubectl- Helm 3
- Container images for the service and Python worker, either the defaults from the chart values or your own image repositories and tags
Runway uses NATS JetStream as its execution queue (see Architecture for details). The service creates the required stream by default when it starts.
The commands below use Bash-style syntax. On Windows, use Git Bash or WSL, or adapt shell-specific details such as ./gradlew and JSON quoting for PowerShell.
Start NATS with JetStream enabled:
docker run --rm -p 4222:4222 nats:latest -jsIn a second terminal, start the service:
cd service
./gradlew bootRunIn Windows PowerShell, run .\gradlew.bat bootRun instead.
The service listens on http://localhost:8080 and creates the default execution_requests stream.
In a third terminal, start the Python worker:
cd python-worker
uv sync
uv run uvicorn executor.app:app --host 0.0.0.0 --port 8000Send a test request:
curl -s -X POST http://localhost:8080/api/v1/execute \
-H 'Content-Type: application/json' \
-d '{"snippet": "print(\"hello from Runway\")", "timeoutMs": 5000, "executionType": "safe"}'Example response:
{
"exitCode": 0,
"stdout": "hello from Runway\n",
"stderr": "",
"executionTimeMs": null
}If the service starts but no worker is running, requests time out and are written to the service dead letter queue.
Create a Docker network and start NATS:
docker network create runway
docker run -d --rm --name runway-nats --network runway -p 4222:4222 nats:latest -jsBuild and run the service:
docker build -t runway-service:local service
docker run -d --rm --name runway-service --network runway -p 8080:8080 \
-e NATS_URL=nats://runway-nats:4222 \
runway-service:localBuild and run the Python worker:
docker build -t runway-python-worker:local python-worker
docker run -d --rm --name runway-python-worker --network runway -p 8000:8000 \
-e NATS_URL=nats://runway-nats:4222 \
runway-python-worker:localThen send the same request to http://localhost:8080/api/v1/execute.
Stop the local Docker setup when you are done:
docker stop runway-python-worker runway-service runway-nats
docker network rm runwayThe Helm chart in charts/runway deploys the service, the Python worker, and, by default, a bundled NATS instance with JetStream enabled.
Install with the default values:
helm upgrade --install runway oci://ghcr.io/jetbrains-research/runway \
--namespace runway \
--create-namespaceFor a local minikube deployment, build the images locally, load them into minikube, and override the chart image values:
docker build -t runway-service:local service
docker build -t runway-python-worker:local python-worker
minikube image load runway-service:local
minikube image load runway-python-worker:local
helm upgrade --install runway charts/runway \
--namespace runway \
--create-namespace \
--set service.image.repository=runway-service \
--set service.image.tag=local \
--set workers.python.image.repository=runway-python-worker \
--set workers.python.image.tag=localWait for the service and Python worker deployments:
kubectl -n runway rollout status statefulset/runway-nats
kubectl -n runway rollout status deployment/runway-service
kubectl -n runway rollout status deployment/runway-python-workerForward the service locally and send a test request:
kubectl -n runway port-forward svc/runway-service 8080:8080curl -s -X POST http://localhost:8080/api/v1/execute \
-H 'Content-Type: application/json' \
-d '{"snippet": "print(\"hello from Kubernetes\")", "timeoutMs": 5000, "executionType": "safe"}'Remove the test deployment when you are done:
helm uninstall runway --namespace runway
kubectl delete namespace runwaySee charts/runway/README.md and charts/runway/values.yaml for chart configuration, image overrides, ingress, scaling, external NATS, and worker sandboxing options.
Runway executes user-provided code. Treat workers as untrusted-workload infrastructure and run them with appropriate isolation for your environment. The Helm chart supports setting a worker runtimeClassName, for example to use a sandboxing runtime such as gVisor when it is available in the cluster.
- docs/README.md: documentation index
- service/README.md: service architecture, configuration, HTTP API, tests, and Docker usage
- python-worker/README.md: worker architecture, execution modes, NATS protocol, tests, and Docker usage
- charts/runway/README.md: Helm installation and chart configuration
- service/loadtest/README.md: k6 load testing
- examples/README.md: example requests, deployments, and integrations
- CONTRIBUTING.md: contribution workflow and local checks
- CONTRIBUTORS.md: contributors
- SECURITY.md: security reporting policy
- docs/release.md: release and versioning process
Runway is licensed under the MIT License.