Documentation Index
Fetch the complete documentation index at: https://docs.dedaluslabs.ai/llms.txt
Use this file to discover all available pages before exploring further.
A scheduled job that wakes a Dedalus Machine, runs your command, sleeps. You pay per-second of compute (only while the job runs) and storage stays warm between runs — your ~/.cache, model weights, and installed packages persist.
DEDALUS_API_KEY=<your-dedalus-key>
MACHINE_ID=<your-machine-id>
1. Provision the machine once
import Dedalus from "dedalus-labs";
const dedalus = new Dedalus({ apiKey: process.env.DEDALUS_API_KEY! });
const m = await dedalus.machines.create({ vcpu: 1, memory_mib: 1024, storage_gib: 10 });
// One-time setup: install whatever your job needs, persists forever.
await runAndWait(m.machine_id, ["/bin/bash", "-c",
"apt-get update && apt-get install -y postgresql-client rclone && rclone config",
]);
console.log("MACHINE_ID=" + m.machine_id);
const fresh = await dedalus.machines.retrieve(m.machine_id);
await dedalus.machines.sleep(m.machine_id, { "If-Match": fresh.revision });
2. The job runner
async function runAndWait(machineId: string, command: string[], timeoutMs = 600_000) {
const exc = await dedalus.machines.executions.create(machineId, { command, timeout_ms: timeoutMs });
let status = exc.status;
while (status !== "succeeded" && status !== "failed") {
await new Promise((r) => setTimeout(r, 500));
const cur = await dedalus.machines.executions.retrieve(machineId, exc.execution_id);
status = cur.status;
}
return dedalus.machines.executions.output(machineId, exc.execution_id);
}
async function runCron() {
const id = process.env.MACHINE_ID!;
let m = await dedalus.machines.retrieve(id);
await dedalus.machines.wake(id, { "If-Match": m.revision });
const out = await runAndWait(id, ["/bin/bash", "-c",
"pg_dump $DATABASE_URL | gzip | rclone rcat backup:nightly/$(date -I).sql.gz",
], 300_000);
console.log(out.stdout);
m = await dedalus.machines.retrieve(id);
await dedalus.machines.sleep(id, { "If-Match": m.revision });
}
runCron().catch((e) => { console.error(e); process.exit(1); });
Run this script from any cron source: GitHub Actions on a schedule, EventBridge, your own k8s CronJob, even another sleeping VM running cron.
When this beats Lambda
- No 250 MB layer hacks. Run anything
apt-get installs.
- No 15-minute timeout. Set
timeout_ms to whatever the job needs.
- Stateful caches.
~/.cache/huggingface (40 GB of weights), ~/.cargo, build artifacts — all persist between runs without an S3 round-trip.
- Per-second billing while awake, zero while sleeping. A 4-second job costs 4 seconds.
- Real Linux. systemd services, persistent
crontab -e if you’d rather schedule inside the VM, full process tree.
Notes
timeout_ms on executions kills the process if it overruns. Without it, executions inherit a generous platform default — set it explicitly for cron.
- Auto-sleep is on by default (
idle_sleep_after_seconds: 300). Even if your script forgets to call sleep(), the machine slips back to zero cost five minutes later.
- Schedule the wake-up itself outside the VM. A sleeping VM can’t wake itself; you need an external scheduler to call
wake on the machine ID.
If-Match is a transitional requirement on mutations — see Lifecycle.