Verlex documentation
Everything you need to run your code in the cloud with Verlex.
On this page
Quick Start
Grab your API key from the dashboard.
Install with pip install verlex (see Installation for details), then run your code on a cloud GPU:
import verlex
# Define your function
def train_model():
import torch
model = torch.nn.Linear(100, 10)
# Your training code here...
return {"accuracy": 0.95}
# Run it on a cloud GPU - that's it!
result = verlex.cloud(train_model, gpu="A100", api_key="gw_your_key")
print(result)Installation
Install Verlex using pip (requires Python 3.10+):
pip install verlexFor automatic cloud offloading with system monitoring:
pip install 'verlex[overflow]'Basic Usage
Pass Your API Key
Every function accepts api_key directly, no context manager needed:
import verlex
# Run in the cloud, one line
result = verlex.cloud(my_function, api_key="gw_your_key")api_key and the resource keywords are keyword-only, so always write them as name=value. There is no separate "mode" argument or test environment: the gw_live_ and gw_test_ prefixes only name the key type; every key runs against the live service with live billing.
Passing Inputs
Your function's inputs come right after the function. A function that takes a single input accepts a bare value; a function that takes two or more inputs must receive them as one list:
# No inputs
verlex.cloud(train_model)
# One input, a bare value is fine
verlex.cloud(square, 5)
# Two or more inputs, pass them as a single list
verlex.cloud(train, [dataset, epochs])Specifying Resources
Override auto-detected resources by listing what you need after the inputs. Each value is recognized by its format, so the order never matters:
# 4 vCPUs, 16 GB RAM, one L40S; units make each value unambiguous
result = verlex.cloud(train_model, [data], "4 vCPUs", "16 GB", "L40S")
# Pin to a provider (a provider name is recognized by shape)
result = verlex.cloud(train_model, [data], "H100", "runpod")
# Offer alternatives: Verlex uses whichever is cheapest and available
result = verlex.cloud(train_model, [data], "H100", "A100")Verlex classifies each spec value by its shape:
"4 vCPUs"→ CPU cores"16 GB"/"512 MB"→ memory- a GPU name like
"H100","A100","L40S","RTX4090"→ GPU type - a provider name:
"aws","gcp","azure","verda","runpod","vast","jarvislabs","hyperstack","tensordock","lyceum","beam","northflank","novita","cerebrium"→ pins the job to that cloud (no failover) - repeat a field (two GPU names, two providers) to offer alternatives. A single provider pins hard with no failover; a list of providers lets Verlex pick the cheapest available
Order never matters, and you can pass the spec however is convenient: as loose values, as one list, or by name with specs=.
# Loose values right after the inputs
result = verlex.cloud(train_model, [data], "H100", "runpod")
# The same spec wrapped in a single list (handy when you build it dynamically)
result = verlex.cloud(train_model, [data], ["H100", "runpod"])
# Or pass that list by name
result = verlex.cloud(train_model, [data], specs=["H100", "runpod"])Group choices as sub-lists to offer soft alternatives. Verlex picks the cheapest available value in each group, and an omitted field (or an empty list) is left for Verlex to choose:
result = verlex.cloud(train_model, [data], [
["4 vCPUs", "8 vCPUs"], # acceptable CPU options
["16 GB", "32 GB"], # acceptable memory options
["H100", "A100"], # acceptable GPU options
["runpod", "gcp"], # acceptable providers
])Prefer explicit keywords? They work too, and take precedence over the list:
result = verlex.cloud(
train_model,
[data],
gpu="A100", # GPU type
cpu=8, # vCPU cores
memory="64GB", # memory
provider="aws", # pin to a cloud (omit to let Verlex pick the cheapest)
timeout=7200, # 2 hour timeout
pip_packages=["numpy==1.26.4"], # extra packages, always installed
python_version="3.11", # match your local Python
)Execution Modes
One flag controls your price-speed tradeoff:
Performance fast=True
Immediate execution
Best for time-sensitive workloads
Standard fast=False
Up to 10 min wait, lower price
Best for batch jobs, cost-sensitive work
# Performance mode, immediate execution
result = verlex.cloud(my_function, api_key="gw_your_key", fast=True)
# Standard mode (default), wait for the lowest price
result = verlex.cloud(my_function, api_key="gw_your_key")Performance mode (fast=True) requires the Performance plan ($10/mo). Standard mode (fast=False) is available on every plan.
Pricing & Billing
Two parts: a monthly plan, then a per-job cost. Verlex passes the provider's live hardware price through at cost and adds a fixed service fee per GPU-hour, prorated per second. There is no percentage markup on the hardware. The Standard plan is free forever ($0/month); the Performance plan ($10/month) unlocks fast mode and 300 GB of storage.
The service-fee tier is derived from the hardware's FP16 tensor performance (TFLOPS):
| Tier | Example hardware | Standard | Performance |
|---|---|---|---|
| CPU (CPU-only jobs) | No GPU | $0.05/hr | $0.10/hr |
| Small (<185 TFLOPS) | T4, L4, A10, RTX 3090 | $0.10/GPU-hr | $0.20/GPU-hr |
| Mid (<600 TFLOPS) | A100, L40S, RTX 4090 | $0.30/GPU-hr | $0.45/GPU-hr |
| Large (<1500 TFLOPS) | H100, H200, MI300X | $0.40/GPU-hr | $0.60/GPU-hr |
| Flagship (≥1500 TFLOPS) | B200, B300, GB200 | $0.50/GPU-hr | $0.75/GPU-hr |
The service fee is charged per GPU-hour. There is no cold-start surcharge; a cold machine and a warm one cost the same.
- Per-second billing, 1 second minimum: you pay only for the time your job actually runs. Both the provider cost and the service fee are prorated to the second.
- Prepaid credits: buy credits in the dashboard (minimum top-up $10). Each job places a hold and settles the exact amount when it finishes.
- Auto top-up (opt-in): adds credits automatically with your saved card when the balance runs low (default: $50 added when it drops below $10).
- Funds-based execution: a job can run until your credits are exhausted, with a hard backstop of 7 days per job. The timeout argument is a client-side wait bound; when it expires, the client cancels the remote job.
Providers, Failover & Serverless
Every job is priced across 10 clouds (AWS, GCP, Azure, Verda, RunPod, Vast.ai, JarvisLabs, Hyperstack, TensorDock, Lyceum) plus four serverless container lanes (Beam, Northflank, Novita, Cerebrium), and routed to the cheapest machine that fits.
import verlex
# Default: priced across 10 clouds, routed to the cheapest machine that fits
result = verlex.cloud(train_model, gpu="A100", api_key="gw_your_key")
# Provider list: cost comparison and failover stay inside your subset
result = verlex.cloud(
train_model,
gpu="A100",
provider=["runpod", "gcp", "verda"],
api_key="gw_your_key",
)
# Hard pin: one provider, no cross-provider failover if it is out of stock
result = verlex.cloud(train_model, gpu="A100", provider="aws", api_key="gw_your_key")If a launch fails or a region is out of stock, Verlex fails over automatically: nearby regions first, then other providers, then substitute GPUs, always cheapest first. Your job does not fail because one cloud ran out of capacity.
Pinning a single provider disables cross-provider failover: if that cloud has no capacity, the job fails instead of moving. Prefer a provider list, which keeps cost comparison and failover inside your chosen subset.
Small jobs are routed to serverless container lanes (billed per second) when that is cheaper than a VM, or faster within budget on the Performance plan. This happens automatically; nothing to configure.
File & Folder Handling
Pass local file or folder paths as arguments, and Verlex automatically uploads them and makes them available in the cloud as temporary files. No manual upload step needed.
import verlex
def train_on_csv(data_path):
import pandas as pd
df = pd.read_csv(data_path)
# ... train model on df
return {"rows": len(df), "columns": list(df.columns)}
# Local file path is detected, uploaded, and available in the cloud
result = verlex.cloud(train_on_csv, "./data/training.csv", api_key="gw_your_key")# Folders work too: automatically zipped, uploaded, and extracted
def process_images(image_dir):
from PIL import Image
import os, tempfile
out = tempfile.mkdtemp()
for f in os.listdir(image_dir):
img = Image.open(os.path.join(image_dir, f))
img = img.resize((224, 224))
img.save(os.path.join(out, f))
return f"Processed {len(os.listdir(out))} images"
result = verlex.cloud(process_images, "./dataset/images", api_key="gw_your_key")File and folder paths must exist locally. Verlex reads and uploads them before execution. Large arguments (over 50 MB) are automatically offloaded regardless of type. Upload blobs are cached for reuse and expire automatically after a period of non-use.
Dependencies
Verlex scans your function's source, pins the versions of imported packages installed locally, and bundles local .py modules automatically. When you need certainty, pass pip_packages=: those packages are authoritative, always installed, and a failed install fails the job loudly instead of continuing silently.
import verlex
def train():
import numpy as np
import torch
from my_helpers import preprocess # local .py modules are bundled automatically
# ... your training code ...
return {"loss": 0.03}
# Auto-detect: imported packages are pinned to your local versions
result = verlex.cloud(train, api_key="gw_your_key")
# Authoritative installs: always installed, a failed install fails the job
result = verlex.cloud(
train,
api_key="gw_your_key",
pip_packages=["torch==2.3.1", "numpy==1.26.4"],
python_version="3.11", # 3.10, 3.11, or 3.12
)python_version controls the interpreter on the cloud side: supported values are 3.10, 3.11, and 3.12. By default Verlex matches your local interpreter.
Automatic Cloud Offloading
Don't want to manage when code runs in the cloud? Let Verlex decide automatically. When your system's CPU, memory, or GPU usage exceeds the threshold, heavy functions are transparently offloaded to the cheapest cloud provider.
import verlex
# Pass your API key directly
verlex.overflow(api_key="gw_your_key")
# Your code runs normally.
# When CPU, memory, or GPU exceeds 85%, functions go to the cloud.
data = load_data()
result = train_model(data) # system overloaded? → cloud
evaluate(result) # resources free → runs locallyParameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| api_key | str | None | None | Your Verlex API key. |
| fast | bool | False | True = Performance mode (immediate execution, premium pricing). False = Standard mode. |
| threshold | float | 85.0 | CPU / memory usage percentage that triggers cloud offloading. Also used as the GPU threshold if gpu_threshold is not set. |
| gpu_threshold | float | None | None | GPU utilization or memory % that triggers cloud offloading. Defaults to threshold if not set. Requires pynvml and an NVIDIA GPU. |
| check_interval | float | 0.5 | Seconds between CPU/memory/GPU samples. |
| api_url | str | None | None | Override the Verlex API URL. |
| verbose | bool | True | Print offload activity and status to the console. |
Defaults: With just an API key, overflow monitors CPU, memory, and GPU. If any of them exceeds 85% usage, functions are automatically offloaded to the cloud in standard mode.
Note: GPU monitoring uses pynvml (included with the base install) and needs an NVIDIA GPU. Without one, overflow gracefully falls back to CPU and memory monitoring only.
CPU and memory monitoring need psutil. Install with: pip install 'verlex[overflow]'
Authentication
Get Your API Key
Sign up at verlex.dev to get your API key.
Using Your API Key
import verlex
# Pass api_key directly to any function
result = verlex.cloud(my_function, api_key="gw_your_key")
# Or use environment variable (VERLEX_API_KEY)
result = verlex.cloud(my_function) # picks up from envGitHub Actions CI/CD
Run cloud GPU jobs from GitHub Actions without storing API keys as secrets. Verlex supports GitHub's OIDC tokens for short-lived, keyless authentication.
# .github/workflows/train.yml
name: Train Model
on: [push]
permissions:
id-token: write # Required for OIDC
jobs:
train:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get Verlex token
id: auth
run: |
OIDC_TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=verlex" | jq -r '.value')
RESPONSE=$(curl -s -X POST https://api.verlex.dev/v1/auth/github-oidc \
-H "Content-Type: application/json" \
-d "{\"token\": \"$OIDC_TOKEN\"}")
echo "api_key=$(echo $RESPONSE | jq -r '.access_token')" >> $GITHUB_OUTPUT
- name: Run training
env:
VERLEX_API_KEY: ${{ steps.auth.outputs.api_key }}
run: |
pip install verlex
verlex run train.py --gpu A100OIDC tokens are scoped to your repository, and the Verlex API key minted from them expires after 24 hours. No long-lived secrets needed.
Note: GitHub OIDC must be enabled per account. Ask your Verlex operator to allowlist your repository (or owner) before using this flow, otherwise the call returns 403.
Error Handling
Verlex raises specific exceptions so you can handle failures gracefully:
from verlex.errors import (
VerlexError, # Base class for all Verlex errors
AuthenticationError, # Invalid or missing credentials
InsufficientCreditsError, # Not enough credits to run the job
ProviderMaintenanceError, # Pinned provider is under maintenance
JobFailedError, # Job execution failed in the cloud
JobTimeoutError, # Job exceeded its timeout
SerializationError, # Function could not be serialized
NetworkError, # Connection to Verlex API failed
RateLimitError, # Too many requests
)
import verlex
try:
result = verlex.cloud(train_model, api_key="gw_your_key", gpu="A100")
except InsufficientCreditsError as e:
print(f"Need more credits: {e.required} required, {e.available} available")
except JobFailedError as e:
print(f"Job {e.job_id} failed in the cloud. Logs:\n{e.logs}")
except ProviderMaintenanceError:
print("That provider is under maintenance. Pick another or drop the pin")
except JobTimeoutError:
print("Job took too long. Increase timeout or optimize your code")
except VerlexError as e:
print(f"Something went wrong: {e}")Available GPUs
Request a GPU by name, either as a spec value (verlex.cloud(fn, [x], "H100")) or with the gpu keyword. Verlex finds the cheapest available instance across 10 clouds, including AWS, GCP, Azure, Verda, RunPod, Vast.ai, JarvisLabs, Hyperstack, TensorDock, and Lyceum, plus serverless lanes on Beam, Northflank, Novita, and Cerebrium.
| GPU | Memory | Best for |
|---|---|---|
| T4 | 16 GB | Inference, small training, budget-friendly |
| L4 | 24 GB | Inference, fine-tuning, video processing |
| A10 | 24 GB | Mixed inference and training |
| V100 | 16 GB | General ML training |
| A100 | 40/80 GB | Large model training, LLM fine-tuning |
| L40S | 48 GB | Large-scale inference and training |
| H100 | 80 GB | Largest models, fastest training |
| H200 | 141 GB | Maximum memory, cutting-edge workloads |
| B200 | 192 GB | Next-gen Blackwell, highest throughput |
| B300 | 288 GB | Blackwell Ultra, largest memory and FP4 throughput |
| RTX 3090 / 4090 / 5090 | 24-32 GB | Budget inference and fine-tuning (consumer cards) |
If you don't specify a GPU, Verlex auto-detects your code's needs and picks the best option. Availability and pricing vary by provider. Verlex always routes to the cheapest option.
Storage & Quotas
Job inputs, outputs, workspace files, and checkpoints live in Verlex object storage and count against your plan's storage quota:
Standard
25 GB of included storage.
Performance
300 GB of included storage.
Enterprise
1 TB of included storage.
Workspace upload blobs are stored by content hash and expire automatically after a period of non-use, so re-uploads of unchanged files are fast.
Teams
Corporate accounts get organization-backed teams: a shared org credit pool, email invitations, and roles (owner, admin, member).
Admins allocate credits from the pool to members and can claw back unused allocations; members can also contribute personal credits to the pool. Everything is managed from the dashboard.
Spending Limits
Set daily or monthly spending caps from your dashboard to prevent unexpected charges. When a limit is reached, Verlex can block new jobs, warn you, or send a notification.
Block
New jobs are rejected until the next period or until you raise the limit.
Warn
Jobs still run, but you get a warning when approaching the limit.
Notify
You receive a notification when the limit is reached. Jobs continue.
Configure spending limits in your dashboard settings. You can also enable auto top-up to automatically add credits when your balance gets low.
CLI Commands
Verlex also ships a CLI for managing jobs from the terminal:
# Login
verlex login
# Run a script
verlex run train.py
# Run with specific GPU
verlex run train.py --gpu A100
# List recent jobs
verlex jobs
# Check a specific job
verlex status <job_id>
# Stream job logs
verlex logs <job_id> --follow
# Cancel a running job
verlex cancel <job_id>
# View account info
verlex whoami
# Show version
verlex version