Outcron Plain HTML

Architecture

Behind the scenes, there is no scene.

Outcron runs as one Go binary — outcrond — that handles API serving, job scheduling, and execution across a shared PostgreSQL database with no leader election, no message broker, and no session state. Add instances for capacity; they coordinate through the database.

Leaderless scheduling and execution

Every outcrond instance runs the same scheduler loop. There is no elected leader, no queue broker, and no sidecar. Instances coordinate entirely through the database using compare-and-swap (CAS) operations and row-level locking.

Each poll cycle, every instance scans for schedules whose next_run_at has passed and attempts to advance it via an atomic CAS update. Only the instance that wins the CAS materializes execution slots for that schedule. A uniqueness constraint on (trigger_type, schedule_id, scheduled_for_at) guarantees exactly one execution row per scheduled slot, even if multiple instances race.

Pending executions are claimed through PostgreSQL's FOR UPDATE SKIP LOCKED, which lets instances claim distinct rows without contention or deadlocks. Each claimed execution runs in a bounded worker goroutine with configurable concurrency limits per executor.

Schedules support timezone-aware cron expressions with configurable misfire policies — skip missed slots, run the latest only, or catch up with a bounded backfill limit. A random splay of up to 45 seconds prevents thundering herds when many schedules fire at the same wall-clock minute.

Execution lifecycle

Every execution moves through a well-defined state machine: pendingclaimedrunningsuccess, failure, or timeout. Pending executions can also be cancelled by users. At each transition, the database timestamp is the source of truth — not the instance's local clock.

Job configuration, schedule metadata, and executor identity are snapshotted at execution start so operators can inspect exactly what ran, even if the job definition changes later. Pending and claimed executions may not have snapshots yet — they are captured when the worker marks the execution as running.

Stale recovery runs continuously. Claimed executions that sit for more than five minutes without transitioning to running are recovered. Running executions are given their full timeout budget plus a 60-second grace period before recovery. Executor instances that miss heartbeats for more than one minute are marked offline; those silent for more than an hour are hard-deleted.

Pending slot materialized
Claimed CAS + SKIP LOCKED
Running snapshot captured
Success
Failure
Cancelled
Timeout stale recovery

One API, three interfaces

outcrond serves a REST API that backs both the web UI and the CLI. The outctl CLI is a pure API client — it has no direct database access, no special protocols, and no privileged endpoints. Everything you can do in the browser, you can do from a terminal, and vice versa.

One binary, full platform

outcrond is a single Go binary that runs the entire platform — API server, job scheduler, executor engine, and metrics endpoint. Every outcrond instance is identical: there are no separate worker, scheduler, or API roles to deploy and manage. Add capacity by running more copies behind a load balancer.

Multi-architecture support

outcrond runs natively on both ARM64 (aarch64) and AMD64 (Intel/AMD) architectures. Container job images can target either architecture, so teams bring their existing images without rebuilding. The outctl CLI ships the same way — single static binaries for both architectures across Linux, macOS, Windows, FreeBSD, NetBSD, and OpenBSD.

Shared PostgreSQL database

All platform state — schedules, executions, jobs, organizations, users, roles, audit logs — lives in a shared, highly available PostgreSQL database. Database time is the authoritative clock for all scheduling decisions, execution timestamps, heartbeats, and stale recovery. No instance carries local state that matters.

Valkey for distributed state

A highly available, Redis-compatible Valkey cluster handles distributed rate limiting via GCRA (Generic Cell Rate Algorithm) backed by Lua scripts for cross-instance consistency.

Stateless web tier

outcrond carries zero web session state. Authentication uses HMAC-SHA256 JWTs with per-request reverification: every request validates the token and confirms the user is still active, still a member of the target org, and that the email claim matches the database. Changing your email or password invalidates all existing sessions immediately.

Granular access control

The platform uses permission tags as the atomic unit of access. Tags are composed into roles, roles are assigned to groups, and groups contain users. API keys use the same permission-tag catalog and can be created from existing roles or with custom tag sets.

System topology

Every outcrond instance is identical — API server, scheduler, and executor in one process. Instances coordinate through shared PostgreSQL and Valkey with no leader election.

Web UI
outctl
API Keys
Load Balancer
outcrond A
API Scheduler Executor
outcrond B
API Scheduler Executor
outcrond N
API Scheduler Executor
Shared data layer
PostgreSQL (state + coordination)
Valkey (rate limiting)

Security by default

Sensitive fields are encrypted at rest with AES-256-GCM using HKDF-SHA256-derived keys with per-field random salts. All traffic is encrypted with TLS 1.2+ and HSTS is enforced with a one-year max-age.

Container jobs run in hardened sandboxes: all Linux capabilities dropped, privilege escalation blocked, read-only root filesystem, PID/memory/CPU limits, non-root user, and an isolated network that blocks cloud metadata endpoints and private IP ranges. HTTP jobs use a SSRF-safe client that validates resolved addresses at dial time.

Every API mutation is audit-logged with field-level diffs, request IDs, and client IPs. Sensitive fields are automatically redacted from audit projections.

Want to learn more?

The security page covers authentication, container isolation, and encryption in more detail. If you have architecture or deployment questions before onboarding, reach out through the contact page.

Security DetailsContact Us