Aiki
Architecture

Server

The Aiki server coordinates workflow execution — and it's a library. server({ db }) returns two pieces:

  • handler — a fetch-style HTTP handler (Request) => Promise<Response> serving the RPC API that clients call. Mount it in any HTTP framework.
  • runtime — background daemons that drive workflow state transitions. Start it with runtime.start().

The bundled standalone server (app/server) is a thin composition of this same library — see Installation.

Request Handling

The RPC API that clients call to:

  • Create workflow runs — validate input, persist state, queue for execution
  • Update workflow state — process state transitions from workers
  • Update task state — record task results and failures
  • Send events — deliver events to waiting workflows
  • Claim ready runs — atomically hand ready work to workers
  • Query runs — list and filter workflow runs

Work Distribution

When a workflow run becomes ready, the server records it in an outbox — the database table that is the source of truth for deliverable work. From there:

  • Default — workers claim pending runs through the server's claim API. No infrastructure beyond the database.
  • With a publisher configured (e.g. @aikirun/redis) — the runtime also pushes ready runs to per-workflow queues the moment they're due, for sub-second delivery. The outbox remains the recovery path: anything lost in transit is re-published.
  • Endpoints (push) — the server sends a signed HTTP request to your endpoint handler; no subscriber involved.

See Subscribers for the worker side of this.

Background Jobs

The runtime's daemons drive workflow state transitions:

DaemonPurpose
Scheduled runsQueue scheduled workflow runs when their start time arrives
Sleep elapsedWake sleeping workflows whose sleep duration has elapsed
Workflow retriesRe-queue workflows in awaiting_retry when their retry delay expires
Task retriesRe-queue workflows whose tasks are awaiting retry
Event wait timeoutsResume workflows that timed out waiting for events
Child wait timeoutsResume workflows that timed out waiting for child workflows
Recurring schedulesCreate new runs for cron and interval schedules
Publish ready runsPublish pending outbox entries to the work queue
Republish stale runsRe-publish runs whose worker stopped heartbeating
Due-timers consumerFire near-term timers from the timer priority queue (when configured)

The two publishing daemons run only when a publisher is configured. Without one, workers claim work directly from the outbox, and stale claims are recovered by the claim API itself.

By default, due work is detected by periodic database scans. Configuring a timer priority queue (@aikirun/redis) promotes near-term timers into a sorted queue that fires them with sub-second precision.

Configuration

Embedded, the server is configured by composition:

import { database, server } from "@aikirun/server";

const aikiServer = server({
  db: database({ provider: "pg", url: databaseUrl }),
});

const runtimeHandle = aikiServer.runtime.start();

Optional pieces plug in the same way — cache, iam (multi-tenancy and auth), and the Redis-backed runtime adapters:

import { redisPublisher, redisTimerPriorityQueue } from "@aikirun/redis";
import { Redis } from "ioredis";

const redis = new Redis({ host: "localhost", port: 6379 });

const aikiServer = server({
  db: database({ provider: "pg", url: databaseUrl }),
  runtime: {
    publisher: redisPublisher(redis),
    timerPriorityQueue: redisTimerPriorityQueue(redis, "aiki:timers"),
  },
});

For the bundled standalone server's environment variables, see the Installation Guide.

Next Steps

On this page