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:

python
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+):

bash
pip install verlex

For automatic cloud offloading with system monitoring:

bash
pip install 'verlex[overflow]'

Basic Usage

Pass Your API Key

Every function accepts api_key directly, no context manager needed:

python
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:

python
# 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:

python
# 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=.

python
# 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:

python
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:

python
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

python
# 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):

TierExample hardwareStandardPerformance
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.

python
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.

python
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")
python
# 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.

python
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.

python
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 locally

Parameters

ParameterTypeDefaultDescription
api_keystr | NoneNoneYour Verlex API key.
fastboolFalseTrue = Performance mode (immediate execution, premium pricing). False = Standard mode.
thresholdfloat85.0CPU / memory usage percentage that triggers cloud offloading. Also used as the GPU threshold if gpu_threshold is not set.
gpu_thresholdfloat | NoneNoneGPU utilization or memory % that triggers cloud offloading. Defaults to threshold if not set. Requires pynvml and an NVIDIA GPU.
check_intervalfloat0.5Seconds between CPU/memory/GPU samples.
api_urlstr | NoneNoneOverride the Verlex API URL.
verboseboolTruePrint 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

python
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 env

GitHub 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.

yaml
# .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 A100

OIDC 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:

python
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.

GPUMemoryBest for
T416 GBInference, small training, budget-friendly
L424 GBInference, fine-tuning, video processing
A1024 GBMixed inference and training
V10016 GBGeneral ML training
A10040/80 GBLarge model training, LLM fine-tuning
L40S48 GBLarge-scale inference and training
H10080 GBLargest models, fastest training
H200141 GBMaximum memory, cutting-edge workloads
B200192 GBNext-gen Blackwell, highest throughput
B300288 GBBlackwell Ultra, largest memory and FP4 throughput
RTX 3090 / 4090 / 509024-32 GBBudget 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:

bash
# 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

Ready to get started?

Create an account and start running code in the cloud.