Skip to content

aikirun/aiki

Repository files navigation

Aiki

Status

A durable execution platform.

Durable execution is a fault tolerant paradigm for building applications, especially long running workflows.

Some workflows take minutes, others take days, months or years. They often need to wait for human interaction, survive crashes, retry on failure, and coordinate across systems. Building these with traditional code means coordinating message queues, crons, state machines, and fragile recovery logic. With Aiki, you focus on writing business logic and let the platform handle durability.

Aiki workflows are like a virtual thread of execution that can be suspended (intentionally or due to crashes/intermittent-failures) and automatically resumed from exactly where they left off.

Example: Subscription Trial

A workflow that activates a 14-day free trial and waits for the user to pay. If payment arrives early, it completes immediately. If the trial expires, the user is downgraded.

import { event, task, workflow } from "@aikirun/workflow";

const activateTrial = task({ name: "activate-trial", async handler(userId: string) { /* ... */ } });
const downgradeToFree = task({ name: "downgrade-to-free", async handler(userId: string) { /* ... */ } });

export const trialV1 = workflow({ name: "subscription-trial" }).v("1.0.0", {
  async handler(run, input: { userId: string }) {
    await activateTrial.start(run, input.userId);

    // Wait up to 14 days — ends early if user pays
    const result = await run.events.paymentReceived.wait({ timeout: { days: 14 } });

    if (result.timeout) {
      await downgradeToFree.start(run, input.userId);
    }
  },
  events: {
    paymentReceived: event(),
  },
});

This looks like ordinary TypeScript, but behind the scenes Aiki makes it durable. The 14-day wait doesn't block workers or consume resources. If the server crashes mid-workflow, it resumes exactly where it left off.

What Aiki handles automatically

  • Crash Recovery — Server can crash at any point. Workflow resumes exactly where it left off.
  • Automatic Retries — Failed tasks retry automatically based on your configured policy.
  • Event Suspension — Waiting for payment suspends the workflow and releases the worker until the event arrives.
  • Durable Sleep — Long waits don't block workers or consume resources.
  • Parallel Execution — Child workflows run on different workers in parallel with the parent.
  • Horizontal Scaling — Add more workers and Aiki distributes work automatically.
Full example: Restaurant Order Workflow

A more complete example showing events with typed data, child workflows, and durable sleep working together.

import { event, workflow } from "@aikirun/workflow";
import { notifyRestaurant, notifyCustomer, sendFeedbackEmail } from "./tasks";
import { courierDeliveryV1 } from "./courier-workflow";

export const restaurantOrderV1 = workflow({ name: "restaurant-order" }).v("1.0.0", {
  async handler(run, input: { orderId: string; customerId: string }) {
    await notifyRestaurant.start(run, input.orderId);

    // Wait for acceptance with 5 min timeout
    const response = await run.events.restaurantAccepted.wait({ timeout: { minutes: 5 } });

    if (response.timeout) {
      await notifyCustomer.start(run, {
        customerId: input.customerId,
        message: "Restaurant didn't respond. Order cancelled.",
      });
      return { status: "cancelled" };
    }

    await notifyCustomer.start(run, {
      customerId: input.customerId,
      message: `Order confirmed! Estimated time: ${response.data.estimatedTime} mins`,
    });

    // Start courier delivery as a child workflow
    const deliveryHandle = await courierDeliveryV1.startAsChild(run, input);
    await deliveryHandle.waitForStatus("completed");

    // Sleep 1 day, then request feedback
    await run.sleep("feedback-delay", { days: 1 });
    await sendFeedbackEmail.start(run, input);

    return { status: "completed" };
  },
  events: {
    restaurantAccepted: event<{ estimatedTime: number }>(),
  },
});

Quick Start

Install the Aiki SDK:

npm install @aikirun/workflow @aikirun/client @aikirun/worker

Start Aiki (requires PostgreSQL — see Installation Guide):

# First clone the repo
git clone https://github.com/aikirun/aiki.git
cd aiki

# Configure your database connection, then start
docker-compose up

# Or run directly with Bun
bun run server  # Terminal 1 - start the server
bun run web     # Terminal 2 - start the web UI

The server runs on http://localhost:9850 and the web UI on http://localhost:9851.

import { client } from "@aikirun/client";
import { worker } from "@aikirun/worker";
import { trialV1 } from "./workflow";

const aikiClient = client({
  url: "http://localhost:9850",
  apiKey: "your-api-key",
});

// Start a worker
const myWorker = worker({
  workflows: [trialV1],
});
const workerHandle = await myWorker.spawn(aikiClient);

// Start a workflow
await trialV1.start(aikiClient, { userId: "user-123" });

// Cleanup
await workerHandle.stop();

Aiki Web UI Demo

Features

Feature Description
Durable Execution Workflows survive crashes and restarts
Child Workflows Modular, reusable sub-workflows
Typed Events Wait for external signals with full TypeScript support
Event Timeouts Set deadlines for human responses
Durable Sleep Sleep for days without blocking workers
Scheduled Execution Start workflows at a future time
Retries Configure retry policies for failed tasks
Horizontal Scaling Add workers to distribute load
Your Infrastructure Workers run in your environment

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                              Your Application                               │
│                    (Uses Aiki SDK to start workflows)                       │
└─────────────────────────────────────┬───────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              Aiki Server                                    │
│                    Orchestrates workflows, manages state                    │
└─────────────────────┬─────────────────────────────────┬─────────────────────┘
                      │                                 │
                      │ Pull (Subscribers)              │ Push (HTTP)
                      ▼                                 ▼
        ┌──────────────────────────┐       ┌──────────────────────────┐
        │  Workers                 │       │  Endpoints               │
        │  Long-lived processes    │       │  Serverless functions    │
        │  in your infrastructure  │       │  on any platform         │
        └──────────────────────────┘       └──────────────────────────┘

Documentation

Read the docs

Requirements

  • Runtime: Node.js 18+ or Bun 1.0+
  • ESM (ES Modules) - This package uses ES modules (import/export)
  • Database: PostgreSQL 14+
  • Redis (optional): Redis 6.2+ for lower-latency work discovery

See the Installation Guide for detailed setup instructions including environment variable configuration.

Packages

License

Apache 2.0 — see LICENSE