# How Apache Mako Achieves Crash Recovery for AI Agent Sessions: A Three-Layer Persistence Architecture

> Discover how Apache Mako ensures AI agent sessions survive crashes. Learn about its three-layer persistence architecture and deterministic replay for robust session recovery.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: internals
- Published: 2026-09-06

---

**Apache Mako ensures AI agent sessions survive process crashes by persisting every state change as an append-only log of immutable `RuntimeEvent`s, using SQLite transactions with crash-boundary semantics to guarantee deterministic replay from the last quiescent snapshot.**

Apache Mako implements robust crash recovery for AI agent sessions through an event-sourced persistence layer that treats every message, tool call, and permission decision as an immutable log entry. According to the Apache Maka source code, the system combines in-memory event streaming with durable SQLite storage and deterministic replay mechanisms to restore exact session states after unexpected termination.

## The Three-Layer Persistence Architecture

Mako's crash recovery system operates through three coordinated layers that transform transient runtime operations into durable, recoverable state.

### In-Memory Event Stream

Every user-visible state change originates as a `RuntimeEvent` in the runtime's admission layer. These events capture messages, tool invocations, permission decisions, and session termination signals. Because the events are immutable and append-only, they form a deterministic history that can reconstruct the entire conversation state.

In [`packages/runtime/src/stream-graph-admission.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/stream-graph-admission.ts), the runtime emits `RuntimeEvent` instances that never mutate after creation. This append-only constraint ensures that replay operations yield bitwise-identical results across recovery attempts.

### Durable SQLite Storage

Events transition from memory to disk through a transactional storage layer that enforces crash-boundary guarantees. The `SessionBundleFileService` in [`packages/storage/src/session-bundle-file-service.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/session-bundle-file-service.ts) manages the persistence pipeline using SQLite with advisory locks and staged write directories.

Every write occurs within a transaction whose commit point defines a crash boundary—for example, after a graph schedule update or intent claim. The system uses staging paths with the pattern `.crash-hydrated.maka-session-bundle-staging-…` to isolate in-flight writes. If a child process crashes, the parent retains the staging inode and can reclaim orphaned files without corrupting sibling sessions.

### Snapshot and Replay Recovery

On startup, the recovery algorithm in [`packages/runtime/src/runtime-resume.ts`](https://github.com/apache/maka/blob/main/packages/runtime/src/runtime-resume.ts) executes a two-phase restoration. First, it loads the most recent quiescent snapshot—a complete session bundle representing a known-good state. Second, it replays all `RuntimeEvent` entries that occurred after the snapshot timestamp.

Because the log is strictly append-only, replay is deterministic. Operations are idempotent: if a crash occurred mid-transaction, the replay either re-applies the operation (if uncommitted) or skips it (if the transaction already committed), leaving the session in a consistent state.

## Crash-Boundary Design for Transactional Safety

Mako's durability guarantees rely on explicit crash-boundary semantics that prevent partial write observation.

### Transaction Commit Points

The storage layer wraps every durable write in a SQLite transaction where the commit point acts as a crash boundary. The test suite in [`packages/storage/src/__tests__/sqlite-runtime-crash.test.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/__tests__/sqlite-runtime-crash.test.ts) deliberately injects crashes at these boundaries to verify that no torn writes survive process termination. This validation ensures that post-crash states are always transactionally consistent.

### Staging Path Isolation

To prevent cross-session corruption, the storage service writes to temporary staging paths before atomically moving completed bundles to their final locations. As implemented in [`session-bundle-file-service.ts`](https://github.com/apache/maka/blob/main/session-bundle-file-service.ts), this approach guarantees that a crash during bundle creation leaves existing sessions untouched. The parent process can later identify and clean up staging files through inode reclamation without risking data loss.

## The Recovery Flow Step-by-Step

When Mako restarts after an unexpected termination, it executes a deterministic recovery protocol.

### Detection and Ledger Validation

The runtime first scans for recovery ledgers—lock files and staged bundle archives that indicate an interrupted session. The presence of these artifacts triggers the recovery pathway rather than a fresh session initialization.

### Snapshot Loading and Event Replay

The system locates the most recent complete session bundle and unpacks it via the `SessionBundleFileService`. Then, [`runtime-resume.ts`](https://github.com/apache/maka/blob/main/runtime-resume.ts) reads the event log from the snapshot timestamp forward, reconstructing the conversation state through sequential event application. Because the UI layer in [`website/src/copy/en.ts`](https://github.com/apache/maka/blob/main/website/src/copy/en.ts) treats the interface as a projection of the event log, the recovered session renders exactly the same prompts and context that the user observed before the crash.

## Implementation Example: Capturing and Recovering State

The following patterns demonstrate the core recovery primitives used throughout the Mako codebase.

Emit a `RuntimeEvent` when a tool call completes:

```typescript
import { RuntimeEvent } from '@maka/runtime';

function recordToolResult(result: any) {
  RuntimeEvent.emit({
    type: 'toolResult',
    payload: result,
    timestamp: Date.now(),
  });
}

```

Persist the event to the durable ledger:

```typescript
import { ModelCallLedger } from '@maka/storage';

async function persistEvent(ev: RuntimeEvent) {
  await ModelCallLedger.append(ev);
}

```

Recover the session on process startup:

```typescript
import { recoverSession } from '@maka/runtime';

async function start() {
  const session = await recoverSession(); // reads snapshot + replays events
  // session now contains the exact state before the crash
}

```

## Summary

- **Append-only event log**: Every state change becomes an immutable `RuntimeEvent` in [`stream-graph-admission.ts`](https://github.com/apache/maka/blob/main/stream-graph-admission.ts), creating a deterministic history for replay.
- **Crash-boundary transactions**: SQLite writes use explicit commit points and staging directories in [`session-bundle-file-service.ts`](https://github.com/apache/maka/blob/main/session-bundle-file-service.ts) to prevent partial state exposure.
- **Quiescent snapshots**: The system captures complete session bundles that serve as known-good restoration points, minimizing replay overhead.
- **Deterministic replay**: The [`runtime-resume.ts`](https://github.com/apache/maka/blob/main/runtime-resume.ts) module rebuilds session state by reapplying events after the latest snapshot, ensuring idempotent recovery.
- **UI projection**: The interface reconstructs solely from replayed events, guaranteeing that post-crash prompts match pre-crash expectations.

## Frequently Asked Questions

### What happens if a crash occurs during a SQLite transaction in Mako?

The transaction either fully commits or fully rolls back. Mako defines crash boundaries at transaction commit points, and the staging file approach ensures that incomplete writes remain isolated in temporary paths. On restart, the recovery system ignores uncommitted staging files and replays only confirmed events from the ledger.

### How does Mako prevent corruption of session bundles during power loss?

The storage layer writes to `.crash-hydrated.maka-session-bundle-staging-…` paths before atomically moving completed bundles to their final destinations. This copy-on-write pattern guarantees that existing session bundles remain read-only during new write operations, eliminating the risk of torn writes corrupting stable data.

### What is a quiescent snapshot in Mako's crash recovery system?

A quiescent snapshot is a complete, consistent archive of session state captured at a specific timestamp. Stored as a session bundle via [`session-bundle-file-service.ts`](https://github.com/apache/maka/blob/main/session-bundle-file-service.ts), it serves as the starting point for recovery. The system replays only those events that occurred after the snapshot timestamp, minimizing recovery time while maintaining full state accuracy.

### How does Mako ensure the UI state matches the recovered session?

The UI layer treats all visual elements as projections of the `RuntimeEvent` log. Because recovery replays the exact sequence of events that occurred before the crash, the reconstructed event stream produces bitwise-identical conversation state. As documented in the website source, the next prompt after recovery is guaranteed to match user expectations because it derives from the same immutable event history.