Comparison
Runqy vs Ray
Ray is a distributed compute framework. Runqy is a task queue. Both can run Python inference on GPUs you own or rent, but they solve different problems.
Ray splits a computation across a cluster. Runqy takes independent jobs from your application and hands each one to a worker, wherever that worker runs. Runqy is our project; this page says when Ray is the better tool.
What you get out of the box
Features available without writing glue code or adding another service.
| Out of the box | Ray | Runqy |
|---|---|---|
| What it is | Distributed compute framework: tasks, actors, Data, Serve, Train | Task queue: jobs in, workers out |
| Submitting work | Python driver; Jobs API and Ray Serve over HTTP | REST API, CLI or Python client, from any language |
| Durable job queue | ✗ tasks live in the running cluster | ✓ Redis, survives restarts |
| Keeps a model loaded between jobs | ✓ actors | ✓ @load |
| GPU-aware placement | ✓ num_gpus, fractional GPUs | ✗ one worker per GPU, routed by queue |
| One job across several GPUs or nodes | ✓ | ✗ |
| Network between machines | Nodes reach the head and each other on a range of ports | Workers only connect out to the server and Redis |
| Ships your code to workers | ✓ runtime_env per job | ✓ git clone + deps per queue |
| Autoscaling machines | ✓ AWS, GCP, Azure, Kubernetes… | ✓ RunPod, Vast.ai |
| Roll out new code to running workers | ~ new job, new runtime_env | ✓ code_update, no restart of the machine |
| Priorities | ✗ | ✓ weighted or strict sub-queues |
| Retries | ✓ max_retries | ✓ per queue |
| Execution timeout | ✗ handle it in your code | ✓ per queue, process restarted |
| Dashboard | ✓ | ✓ |
| Alerts | ~ via Prometheus and Grafana | |
| Secrets for workers | ✗ | ✓ encrypted vaults |
| License | Apache-2.0 | MIT |
✓ built in · ~ partial or limited · ✗ not built in (you add a separate tool or write it yourself)
Choose Ray when
- One job needs several GPUs or several nodes (tensor parallelism, distributed training).
- You want GPU-aware scheduling: Ray places each task where the GPUs are free.
- You process datasets in parallel with Ray Data, or serve models online with dynamic batching through Ray Serve.
- Your machines share a network, such as one cloud region or one Kubernetes cluster.
Choose Runqy when
- Your application submits independent jobs over HTTP and reads the results later.
- Workers are scattered: a GPU at home, a lab server, rented machines. They only need outbound access.
- Rented GPUs come and go, and you want RunPod or Vast.ai machines started and stopped with the queue.
- You want a durable queue with priorities, timeouts, alerts and secrets, without building it on top of a framework.
The same GPU worker, both ways
Ray actor
import ray
@ray.remote(num_gpus=1)
class Generator:
def __init__(self):
self.pipe = load_pipeline()
def generate(self, prompt):
return self.pipe(prompt)
gen = Generator.remote()
image = ray.get(gen.generate.remote("a fox")) The driver holds the reference. If the cluster goes down, pending work is gone.
Runqy task
from runqy_python import load, task, run
@load
def setup():
return {"pipe": load_pipeline()}
@task
def generate(payload, ctx):
return save(ctx["pipe"](payload["prompt"]))
run()
# Enqueue from anywhere:
# POST /queue/add {"queue": "images", "data": {...}} Jobs wait in Redis until a worker takes them, with retries and timeouts per queue.
Using both
They also combine. A Runqy worker can start a Ray job inside a task when one request needs a multi-GPU computation, while Runqy keeps the queue, the priorities and the machines.
Try Runqy
Open source and self-hosted. Redis, the server and a worker run with one Docker Compose file.