Skip to main content

Hybrid GPU Inference Orchestrator — serverless for cold starts, spot for scale

Project description

Tuna

Tuna

Spot GPUs are 3-5x cheaper than on-demand, but they take minutes to start and can be interrupted at any time. Serverless GPUs start in seconds and never get interrupted, but you pay a premium for that convenience. What if you didn't have to choose?

Tuna is a smart router that combines both behind a single OpenAI-compatible endpoint. It serves requests from serverless while spot instances boot up, shifts traffic to spot once ready, and falls back to serverless if spot gets preempted. You only pay for the compute you actually use — spot rates for steady traffic, serverless only during cold starts and failover.

Serverless Spot

Modal

RunPod

Cloud Run

AWS via SkyPilot

Prerequisites

  • Python 3.11+
  • AWS CLI — required for spot instances (all deployments use spot)
  • At least one serverless provider account: Modal, RunPod, or Google Cloud
  • For gated models (Llama, Mistral, Gemma, etc.): a HuggingFace token with access to the model

Note: Tuna always deploys both a serverless backend and a spot backend. AWS credentials are required even if your serverless provider is Modal or RunPod, because spot instances run on AWS via SkyPilot.

Quick Start

1. Install

pip install tandemn-tuna[modal] --pre     # Modal as serverless provider
pip install tandemn-tuna[cloudrun] --pre  # Cloud Run as serverless provider
pip install tandemn-tuna --pre            # RunPod (no extra deps needed)
pip install tandemn-tuna[all] --pre       # everything

This project is under active development and experimental. For the latest version, install from source:

git clone https://github.com/Tandemn-Labs/tandemn-tuna.git
cd tandemn-tuna
pip install -e ".[all]"

2. Set up AWS (required for all deployments)

aws configure          # set up AWS credentials
sky check              # verify SkyPilot can see your AWS account

3. Set up your serverless provider (pick one)

Modal
modal token new
RunPod
export RUNPOD_API_KEY=<your-key>  # https://www.runpod.io/console/user/settings

Add this to your ~/.bashrc or ~/.zshrc to persist it.

Cloud Run

Requires the gcloud CLI.

gcloud auth login
gcloud auth application-default login    # required for the Python SDK
gcloud config set project <YOUR_PROJECT_ID>

You also need billing enabled and the Cloud Run API (run.googleapis.com) enabled on your project.

4. (Optional) Set HuggingFace token for gated models

export HF_TOKEN=<your-token>  # https://huggingface.co/settings/tokens

Required for models like Llama, Mistral, Gemma, and other gated models. Not needed for open models like Qwen.

5. Validate your setup

tuna check --provider modal                          # check Modal credentials
tuna check --provider runpod                         # check RunPod API key
tuna check --provider cloudrun --gcp-project <id> --gcp-region us-central1  # check Cloud Run

6. Deploy a model

tuna deploy --model Qwen/Qwen3-0.6B --gpu L4 --service-name my-first-deploy

Tuna auto-selects the cheapest serverless provider for your GPU, launches spot instances on AWS, and gives you a single endpoint. The router handles everything — serverless covers traffic immediately while spot boots up in the background.

7. Send requests (OpenAI-compatible)

curl http://<router-ip>:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "Qwen/Qwen3-0.6B", "messages": [{"role": "user", "content": "Hello"}]}'

8. Monitor and manage

tuna status --service-name my-first-deploy    # check deployment status
tuna cost --service-name my-first-deploy      # real-time cost dashboard
tuna list                                     # list all deployments
tuna destroy --service-name my-first-deploy   # tear down everything

Tip: If you don't pass --service-name during deploy, Tuna auto-generates a name like tuna-a3f8c21b. Use tuna list to find it.

9. Browse GPU pricing

tuna show-gpus                     # compare serverless pricing across providers
tuna show-gpus --spot              # include AWS spot prices
tuna show-gpus --gpu H100          # detailed pricing for a specific GPU
tuna show-gpus --provider runpod   # filter to one provider

Architecture

                ┌──────────────────────┐
                │    User Traffic      │
                │ (OpenAI-compatible)  │
                └──────────┬───────────┘
                           │
                  ┌────────▼────────┐
                  │  Smart Router   │
                  │  (meta_lb)      │
                  └────────┬────────┘
                           │
              ┌────────────┴────────────┐
              │                         │
     ┌────────▼─────────┐    ┌─────────▼─────────┐
     │ Serverless        │    │ Spot GPUs          │
     │ Modal / RunPod /  │    │ AWS via SkyPilot   │
     │ Cloud Run         │    │                    │
     │                   │    │ • 3-5x cheaper     │
     │ • Fast cold start │    │ • Slower cold start│
     │ • Per-second bill │    │ • Auto-failover    │
     │ • Always ready    │    │ • Scale to zero    │
     └───────────────────┘    └────────────────────┘

The router:

  • Routes to serverless while spot instances are starting up
  • Shifts traffic to spot once ready (cheaper)
  • Falls back to serverless if spot has issues or high latency
  • Scales serverless down to zero when spot is serving

CLI Reference

Command Description
deploy Deploy a model across serverless + spot
destroy Tear down a deployment
status Check deployment status
cost Show cost dashboard (requires running deployment)
list List all deployments (filter with --status active|destroyed|failed)
show-gpus GPU pricing across providers (filter with --provider, --gpu, --spot)
check Validate provider credentials and setup

deploy flags

Flag Default Description
--model (required) HuggingFace model ID (e.g. Qwen/Qwen3-0.6B)
--gpu (required) GPU type (e.g. L4, L40S, A100, H100)
--gpu-count 1 Number of GPUs
--serverless-provider auto (cheapest for GPU) modal, runpod, or cloudrun
--spots-cloud aws Cloud provider for spot GPUs
--region Cloud region for spot instances
--tp-size 1 Tensor parallelism degree
--max-model-len 4096 Maximum sequence length (context window)
--concurrency Override serverless concurrency limit
--workers-max Max serverless workers (RunPod only)
--cold-start-mode fast_boot fast_boot (uses --enforce-eager, faster startup but lower throughput) or no_fast_boot
--no-scale-to-zero off Keep minimum 1 spot replica running
--scaling-policy Path to scaling YAML (see below)
--service-name auto-generated Custom service name (recommended — makes status/destroy easier)
--public off Make service publicly accessible (no auth)
--use-different-vm-for-lb off Launch router on a separate VM instead of colocating on controller
--gcp-project Google Cloud project ID
--gcp-region Google Cloud region (e.g. us-central1)

Use -v / --verbose with any command for debug logging.

Scaling Policy

All autoscaling parameters can be configured via a YAML file passed with --scaling-policy. If omitted, sane defaults apply.

spot:
  min_replicas: 0        # 0 = scale to zero (default)
  max_replicas: 5
  target_qps: 10         # per-replica QPS target
  upscale_delay: 5       # seconds before adding replicas
  downscale_delay: 300   # seconds before removing replicas

serverless:
  concurrency: 32        # max concurrent requests per container
  scaledown_window: 60   # seconds idle before scaling down
  timeout: 600           # request timeout in seconds
  workers_min: 0         # min workers (RunPod only)
  workers_max: 1         # max workers (RunPod only)
  scaler_value: 4        # queue delay scaler threshold (RunPod only)

Precedence: defaults <- YAML file <- CLI flags. For example, --concurrency 64 overrides serverless.concurrency from the YAML. --no-scale-to-zero forces spot.min_replicas to at least 1 and sets serverless.scaledown_window to 300s.

Unknown keys in the YAML will error immediately (catches typos).

Troubleshooting

Setup issues

Start with the built-in diagnostic tool:

tuna check --provider runpod
tuna check --provider modal
tuna check --provider cloudrun --gcp-project <id> --gcp-region us-central1

This validates credentials, API access, project configuration, and GPU region availability.

Endpoint not responding

# Check your deployment status
tuna status --service-name <name>

# Check router health directly
curl http://<router-ip>:8080/router/health

# Check SkyServe status
sky status --refresh

High latency

Check which backend is serving traffic:

curl http://<router-ip>:8080/router/health

If skyserve_ready is false, spot instances are still booting — requests are going through serverless (which is working correctly). Once spot boots, traffic shifts automatically.

Gated model fails to load

If the deployment succeeds but the model fails to start, you likely need a HuggingFace token:

export HF_TOKEN=<your-token>

Then redeploy.

Contact

License

MIT

This project depends on SkyPilot (Apache License 2.0).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tandemn_tuna-0.0.1a5.tar.gz (63.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tandemn_tuna-0.0.1a5-py3-none-any.whl (52.1 kB view details)

Uploaded Python 3

File details

Details for the file tandemn_tuna-0.0.1a5.tar.gz.

File metadata

  • Download URL: tandemn_tuna-0.0.1a5.tar.gz
  • Upload date:
  • Size: 63.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tandemn_tuna-0.0.1a5.tar.gz
Algorithm Hash digest
SHA256 404915b5d15c063103a235c2947b8e34c77e14eb5b14461c7482edbbb41c8541
MD5 a481c72afddb596e67521164a2a042bf
BLAKE2b-256 5a9ad429a8894e29bd719c918a452e4e55d5a71d0b45b62b925169a060218404

See more details on using hashes here.

File details

Details for the file tandemn_tuna-0.0.1a5-py3-none-any.whl.

File metadata

  • Download URL: tandemn_tuna-0.0.1a5-py3-none-any.whl
  • Upload date:
  • Size: 52.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22.2","id":"zara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for tandemn_tuna-0.0.1a5-py3-none-any.whl
Algorithm Hash digest
SHA256 285e692562cf4b17741dff99991116729fd4b530bd8bd64cd259c33ed0ff37d4
MD5 cb43a7c0a8167bf5bad99bf795e02240
BLAKE2b-256 4e7bc3264faf47f6997064509bfb67bf9c113b5fa8cd2738d80ea5212094db33

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page