An open API service indexing awesome lists of open source software.

https://github.com/aikirun/aiki

Durable Execution Platform
https://github.com/aikirun/aiki

distributed-systems durable-execution durable-functions event-driven fault-tolerance orchestrator queue typescript workflow-automation workflow-engine workflows

Last synced: 2 months ago
JSON representation

Durable Execution Platform

Awesome Lists containing this project

README

          


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.

```typescript
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.

```typescript
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:
```bash
npm install @aikirun/workflow @aikirun/client @aikirun/worker
```

Start Aiki (requires PostgreSQL — see [Installation Guide](./docs/getting-started/installation.md)):

```bash
# 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`.

```typescript
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](./docs/README.md)

## 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](./docs/getting-started/installation.md) for detailed setup instructions including environment variable configuration.

## Packages

- [`@aikirun/workflow`](https://www.npmjs.com/package/@aikirun/workflow) — Workflow and Task SDK
- [`@aikirun/client`](https://www.npmjs.com/package/@aikirun/client) — Client SDK
- [`@aikirun/worker`](https://www.npmjs.com/package/@aikirun/worker) — Worker SDK
- [`@aikirun/endpoint`](https://www.npmjs.com/package/@aikirun/endpoint) — Endpoint SDK (serverless)
- [`@aikirun/redis`](https://www.npmjs.com/package/@aikirun/redis) — Redis transport (optional)

## License

Apache 2.0 — see [LICENSE](LICENSE)