How Apache Maka Ensures Durable Runtime Event Persistence Against Crashes

Apache Maka guarantees crash-resilient event persistence by recording every agent interaction in an append-only SQLite database (runtime.sqlite) with transactional writes, strict schema versioning, and deterministic recovery protocols.

All runtime events—model messages, tool calls, tool results, and termination facts—are stored in a single Runtime Event Log that survives process termination, system crashes, or power loss. On restart, Maka reopens this log to reconstruct exact run states and resume safely without duplicating side effects.

Single Canonical Store with Transactional Durability

Apache Maka centralizes all runtime facts in one SQLite database. The SqliteRuntimeStore class in packages/storage/src/sqlite-runtime-store.ts executes every insert inside a single transaction, leveraging SQLite's ACID guarantees (v3.35+) for atomicity and durability.

// packages/storage/src/sqlite-runtime-store.ts
// All events are inserted transactionally
await db.run('BEGIN TRANSACTION');
// ... insert statements
await db.run('COMMIT');

This design eliminates partial writes. Either the entire event batch persists to disk, or none of it does—preventing corruption even if the process terminates mid-write.

Append-Only Semantics Prevent History Loss

Events are never modified or deleted. Compaction and pruning operations only affect provider projections; the underlying facts in runtime.sqlite remain immutable. As documented in ARCHITECTURE.md, this append-only approach ensures accidental operations cannot erase execution history.

Hardened Schema with Protective PRAGMAs

The runtime schema enforces durability through explicit configuration:

PRAGMA Purpose
busy_timeout Prevents lock contention timeouts
foreign_keys Maintains referential integrity
query_only (read mode) Blocks accidental writes during recovery

The schema version (SQLITE_RUNTIME_SCHEMA_VERSION) in packages/storage/src/sqlite-runtime-schema.js enables migration detection and prevents opening incompatible database files.

Recovery-First Design for Crash Scenarios

When Maka restarts after a crash, the recovery protocol activates before any new run begins. The system calls openRuntimeEventPersistence (or openRuntimeEventReadPersistence for read-only access) to:

  1. Reopen runtime.sqlite
  2. Replay immutable events to reconstruct run state
  3. Resolve terminal status using the recovery resolver

Per docs/architecture/runtime-resume-architecture.md, the recovery resolver examines stored events to classify tool operations as:

  • Completed — result was persisted
  • Unknown — outcome indeterminate, requires parking
  • Pending — never executed, safe to retry

Transactional Claims Prevent Duplicate Side Effects

The claimContinuation mechanism protects against exactly-once violations. When a run claims a continuation, the claim and its triggering event are written together. If the process dies mid-write, the next startup detects the missing claim and treats the run as unfinished—preventing duplicate tool executions.

// From packages/storage/src/sqlite-runtime-store.ts
await persistence.runtimeEventStore.appendRuntimeEvent(
  'session-1',
  'run-42',
  {
    id: 'evt-123',
    ts: Date.now(),
    content: { kind: 'function_call', name: 'readFile', args: { path: 'foo.txt' } },
  },
  { durable: true }  // Forces fsync to disk
);

The durable: true option ensures SQLite executes fsync, guaranteeing the write survives power loss.

Authority Isolation for Deterministic State

The Runtime Event Log is the sole source of truth. All other components—Graph, Context, and UI—maintain only projections derived from this log. This isolation eliminates divergent state and makes recovery deterministic: replay the same events, reconstruct the same state.

Working with Runtime Event Persistence

Opening Writable Persistence

import { openRuntimeEventPersistence } from '@maka/storage';

const persistence = await openRuntimeEventPersistence({
  workspaceRoot: '/my/workspace'
});
// Creates or opens runtime.sqlite in the workspace

Appending Events Durably

await persistence.runtimeEventStore.appendRuntimeEvent(
  'session-1',
  'run-42',
  {
    id: 'evt-123',
    ts: Date.now(),
    content: { 
      kind: 'function_call', 
      name: 'readFile', 
      args: { path: 'foo.txt' } 
    },
  },
  { durable: true }
);

Recovery and Replay

import { openRuntimeEventReadPersistence } from '@maka/storage';

const readOnly = await openRuntimeEventReadPersistence({
  workspaceRoot: '/my/workspace'
});

const events = await readOnly.runtimeEventStore.readRuntimeEvents(
  'session-1', 
  'run-42'
);
// events contains the immutable, ordered log for reconstruction

Key Implementation Files

File Responsibility
packages/storage/src/sqlite-runtime-store.ts Core SQLite operations, transactions, and durability guarantees
packages/storage/src/runtime-event-persistence.ts High-level persistence layer initialization
packages/storage/src/sqlite-runtime-schema.js Schema definitions and version tracking
ARCHITECTURE.md System-wide architecture documentation
docs/architecture/runtime-resume-architecture.md Crash recovery and continuation protocols

Summary

  • Runtime Event Log in runtime.sqlite provides durable, append-only event storage
  • Transactional writes via SqliteRuntimeStore guarantee atomic persistence
  • Schema versioning and PRAGMAs protect against corruption
  • Recovery-first startup reconstructs state before accepting new work
  • Transactional claims prevent duplicate side effects after crashes
  • Authority isolation ensures deterministic recovery through event replay

Frequently Asked Questions

How does Apache Maka prevent data loss during a power failure?

Maka uses durable writes with SQLite's fsync guarantee. The durable: true flag in appendRuntimeEvent forces the operating system to flush data to physical storage before returning. Combined with SQLite's WAL mode and transactional boundaries, events survive power loss regardless of when the crash occurs.

Can Maka resume a run that crashed mid-tool-execution?

Yes. The recovery resolver examines the immutable event log to determine tool completion status. In docs/architecture/runtime-resume-architecture.md, Maka defines three states: completed operations resume with stored results, unknown operations are parked for manual review, and pending operations retry safely.

Why does Maka use SQLite instead of a distributed database?

SQLite provides single-file portability, zero external dependencies, and proven crash durability—critical for a local-first agent runtime. The runtime.sqlite file travels with the workspace, enabling seamless transfer and offline operation without network requirements.

What happens if the database file becomes corrupted?

The schema version check and PRAGMA integrity constraints detect corruption early. Maka opens read-only stores with query_only enabled during recovery, preventing further damage. For unrecoverable corruption, the append-only design means partial event logs may still be salvageable for forensic reconstruction.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →