sdks
SDKs
Every port ships the same numbered scenarios in the same order, so a concept you learn in one language transfers directly to the next. Pick a language once below and the whole page follows it.
Each snippet on this page is extracted from a program in sdk/<lang>/examples/
that the test suite runs end to end on every CI pass — not copied into the
docs by hand.
01 · Heartbeat
Section titled “01 · Heartbeat”The one thing curl already does well: say “I ran and I succeeded”. Everything
after this is something a one-line HTTP request can’t express.
import deadpost
rotate_logs()deadpost.ping() # "I ran and succeeded"import { ping } from '@deadpost/sdk';
await rotateLogs();await ping(); // "I ran and succeeded"02 · Timed run
Section titled “02 · Timed run”A heartbeat says the job finished. A run says when it started, when it finished, and how long it took — so you can alert on a backup that still succeeds but has quietly gone from four minutes to forty.
import deadpost
with deadpost.run() as run: rebuild_search_index()import { run } from '@deadpost/sdk';
await run(async (job) => { const docs = await rebuildSearchIndex(); job.tag({ docs });});03 · Failure
Section titled “03 · Failure”An exception marks the run failed and is then re-raised unchanged. Your error handling keeps working exactly as it did; deadpost just learns about it.
import deadpost
try: with deadpost.run() as run: dump_database()except ConnectionError as exc: # deadpost already reported the failure. This is your own handling — # the exception reached you exactly as it was raised. print(f"backup failed: {exc}")import { run } from '@deadpost/sdk';
try { await run(async () => { await exportToWarehouse(); // throws -> /fail, then re-thrown unchanged });} catch (err) { console.error('job failed:', err.message);}04 · Tags
Section titled “04 · Tags”Attach numbers to a run — rows processed, bytes written — and read them back per run in the dashboard.
import deadpost
with deadpost.run(env="prod", region="eu-central") as run: rows, size = dump_database() run.tag(rows=rows, bytes=size)import { run } from '@deadpost/sdk';
await run({ env: 'prod', region: 'eu-central' }, async (job) => { const { rows, bytes } = await dumpDatabase(); job.tag({ rows, bytes });});05 · Many monitors
Section titled “05 · Many monitors”One client, several monitors addressed by name. The common shape once a single process owns more than one scheduled job.
from deadpost import Deadpost
# Reads DEADPOST_TOKEN_DAILY_BACKUP and DEADPOST_TOKEN_NIGHTLY_ETL — one# environment variable per monitor, the shape secret managers already have.dp = Deadpost()
take_backup()dp.ping("daily-backup")
with dp.run("nightly-etl") as run: run.tag(rows=run_etl())import { Deadpost } from '@deadpost/sdk';
// Names also come from DEADPOST_TOKEN_DAILY_BACKUP in the environment.const dp = new Deadpost({ monitors: { 'daily-backup': process.env.BACKUP_TOKEN } });
await dp.ping('daily-backup');await dp.run('nightly-etl', async (job) => job.tag({ rows: await etl() }));06 · Offline spool
Section titled “06 · Offline spool”Pings are buffered to disk through a network blip and replayed when the connection returns, so a flaky link doesn’t read as a dead job.
from deadpost import Deadpost
dp = Deadpost( spool=True, max_replay_age=300, # 5 minutes — keep it under the monitor's grace period)
result = dp.ping(rows=17)if result.spooled: print("network is down; check-in buffered, will replay on the next success")import { Deadpost } from '@deadpost/sdk';
const dp = new Deadpost({ spool: true }); // or DEADPOST_SPOOL=1
const result = await dp.ping();if (result.spooled) console.log('buffered; it will replay on the next success');07 · Language-idiomatic
Section titled “07 · Language-idiomatic”The last scenario is deliberately different in each port — Python gets a decorator, Node gets a Lambda handler — because the point is to show what the SDK feels like when it fits the language it lives in.
import deadpost
@deadpost.monitor(env="prod")def nightly_etl() -> int: rows = fetch_rows() return rows
nightly_etl()import { run } from '@deadpost/sdk';
export async function handler(event) { return run(async (job) => { const processed = await processBatch(event); job.tag({ processed }); return { statusCode: 200 }; });}