Skip to content
Pyrula
Pre-release: the packages are not on PyPI yet, so pip install does not resolve. Build from source to try it today.

Production checklist

Nothing here is checked for you unless the item says so.

  • One host, local disk. A network filesystem or a second host is refused at open (Choosing a store).
  • Low traffic only. One writer serves every worker, and synchronous=full waits for fsync on each commit. Use Valkey for production load (why).
  • Linux, not macOS. macOS fsync does not flush the drive cache, so commits can be lost on power loss.
  • Back up with pyrula store backup DEST on a schedule, not by copying the .db file. There is no replication.
  • Disk for retention. Finished runs are kept 7 days (retention_seconds); pyrula store info shows the size.
  • Valkey 7.2+ or Redis 6.0+, with SCRIPT LOAD and EVALSHA allowed. The store loads one Lua script and calls it by its hash. A user whose ACL denies them fails at startup with the grants to add (recipe).
  • maxmemory-policy noeviction, on an instance dedicated to pyrula. allkeys-* deletes live run journals under memory pressure, so ValkeyStore refuses it while maxmemory is above zero (PYRULA_VALKEY_EVICTION_CHECK=warn|off accepts the risk, Installation). volatile-* only warns: run locks, leases and dedupe keys carry no TTL, so it can drop finished-run history and a few short-lived keys (which). ElastiCache, Memorystore, Azure Managed Redis and Redis Cloud default to volatile-lru and Render to allkeys-lru; Managed Valkey and Redis gives each one’s fix. ElastiCache Serverless fixes volatile-lru, so alarm on evicted_keys there. Checked for you: pyrula dev --check --store URL and pyrula db check --store URL fail on allkeys-* and warn on volatile-* before deploy.
  • Persistence on: appendonly yes or an RDB save schedule. Without it a restart loses every in-flight run. The store cannot check this; verify on the server.
  • A namespace per environment when several share an instance (PYRULA_VALKEY_NAMESPACE).

Postgres holds completed runs; live state stays in Valkey. Install "pyrula[workflows,postgres]" (pyrula-agents already depends on it), run pyrula db migrate --postgres-dsn "$PYRULA_POSTGRES_DSN" once, then pyrula db check --store ... --postgres-dsn ... before starting workers. A database older or newer than the code supports fails with ArchiveSchemaMismatch (Versioning & stability, Workers).

  • Run a worker tier. Sleeps, signal waits, interrupts, children and schedules need a WorkflowWorker or pyrula worker; nothing else wakes those runs (Deployment modes, Deploy a worker).
  • Agents: don’t ship embedded mode. An agent under pyrula dev or create_app’s default refuses ctx.sleep, ctx.sleep_until, ctx.run_child, ctx.spawn_workflow, ctx.gather_subagents and waits with a deadline (details).
  • Give each worker a stable id. WorkflowWorker(worker_id=...) defaults to a random id per process; use the host or instance name so logs and leases agree across restarts. Do the same with PYRULA_RUNTIME_ID for Cloud.
  • Know the runbook commands. pyrula runs list --status error --since 1h, pyrula runs show RUN_ID --journal, and pyrula runs cancel|terminate|retry read the store PYRULA_STORE_URL names and need no running worker (CLI reference).

Put auth on every HTTP surface a non-loopback address can reach; with no provider, anyone who can reach the port can submit, stream, cancel and resume runs. The startup refusal for an open non-loopback bind only sees hosts declared in AppOptions(host=..., auth=...), not a bare uvicorn.run. See Serving auth.

pyrula schedules create derives the id from agent, cron and params, so re-running it is a no-op. store.schedule_create with Schedule.create(...) mints a random id unless you pass schedule_id=. Pick one path per job, or two schedules fire. Cron runs in the schedule’s time zone (UTC by default) and missed occurrences are not backfilled (Schedules, Workers).

Set PYRULA_CLOUD_API_KEY in the worker’s environment and install "pyrula[cloud]"; a key without the client is an error, and without a key nothing is sent. A store belongs to one project and environment. See Connect to Pyrula Cloud and What leaves your runtime.

View this page as Markdown