Skip to main content

Runs

Ephemeral batch compute. Spawn fire-and-forget containers that run to completion — ML training, ETL, data processing at scale. Any language, any image.

Runs vs Tasks

Tasks are TypeScript handlers with durable execution (queues, retries, step.run, step.sleep) — ideal for API-triggered work like sending emails or processing webhooks.
Runs are ephemeral containers that run to exit — ideal for ML training, ETL pipelines, and batch workloads where you bring your own image (Python, Go, Rust, etc.).

Parallel Execution

Spawn N runs simultaneously with Promise.all() — fan-out workloads made simple

Run to Completion

Container runs until exit — no idle timeouts, no heartbeats needed

Shared Volume Mounts

Mount shared volumes for feature caches across parallel runs

Machine Profiles

Pick a managed machine size for predictable cost and performance

Log Capture

Full stdout + stderr captured and stored on completion (1 MiB each)

Quick Start

train.ts
import { RunsClient, createClient } from '@sylphx/sdk'

// Connection URL bundles credential + slug — no separate ref env var needed
const config = createClient(process.env.SYLPHX_URL!)

// Single run — wait for completion
const result = await RunsClient.runAndWait(config, {
  image: 'ghcr.io/acme/trainer:sha-abc123',
  command: ['python', 'train.py', '--fold', '0'],
  machine: 'large',
  timeoutSeconds: 3600,
})

if (result.exitCode !== 0) {
  throw new Error(`Training failed: ${result.stderr}`)
}
console.log('Accuracy:', JSON.parse(result.stdout).accuracy)

Parallel Walk-Forward Training

Spawn multiple runs in parallel, each processing a different data fold:

train-parallel.ts
import { RunsClient, createClient } from '@sylphx/sdk'

const config = createClient(process.env.SYLPHX_URL!)

const folds = [0, 1, 2, 3, 4, 5, 6, 7, 8]

// Spawn all runs in parallel
const handles = await Promise.all(
  folds.map((fold) =>
    RunsClient.run(config, {
      image: 'ghcr.io/acme/trainer:sha-abc123',
      command: ['python', 'train.py', '--fold', String(fold)],
      env: { FOLD_ID: String(fold), DATABASE_URL: process.env.DATABASE_URL! },
      machine: 'large',
      // Shared feature cache volume for concurrent access.
      volumeMounts: [{ volumeId: process.env.CACHE_VOLUME_ID!, mountPath: '/cache' }],
      timeoutSeconds: 7200,
    }),
  ),
)

// Wait for all to complete
const results = await Promise.all(handles.map((h) => h.wait()))
const failures = results.filter((r) => r.exitCode !== 0)
if (failures.length > 0) {
  console.error(`${failures.length}/${folds.length} folds failed`)
}
const avgAccuracy = results
  .filter((r) => r.exitCode === 0)
  .map((r) => JSON.parse(r.stdout).accuracy)
  .reduce((a, b) => a + b, 0) / folds.length
console.log('Average accuracy:', avgAccuracy)

Configuration Reference

PropertyTypeDescription
imagerequiredstringOCI image from a connected registry.
commandrequiredstring[]Command and arguments to run inside the container.
envRecord<string, string>Environment variables injected into the container.
machine'nano' | 'micro' | 'small' | 'standard' | 'large' | 'xlarge'Managed machine size. Defaults to standard; the platform owns scheduling and isolation.
volumeMountsRunVolumeMount[]Volumes to mount. Use shared volumes for cross-run sharing.
timeoutSecondsnumberHard deadline. Run is killed if exceeded. Default: 3600 (1h), max: 86400 (24h).

RunHandle API

PropertyTypeDescription
handle.idstringRun ID (run_xxxxx). Store this to poll later.
handle.wait(options?)Promise<RunResult>Polls until terminal state. Returns RunResult with exitCode, stdout, stderr.
handle.statusRunStatusCurrent status at time of creation: pending | running | succeeded | failed | cancelled | timeout

Pricing

Billed per compute-second based on the selected machine and actual runtime. Runs that exit early are billed for actual duration only.

PropertyTypeDescription
Free tierAll plans100K standard compute-seconds per month
Beyond free tierUsage-basedUsage-based by machine size and duration

Cost example

9 parallel large runs × 600s each bill as 5,400 large compute-seconds. Free tier credits apply automatically before usage-based billing.