docs/architecture/index.md
This document explains how Beads' architecture works with Dolt as its storage backend: the storage layout, the data model, and the sync paths. For the concept model — beads, dependencies, ready work, molecules — see How Beads Works.
Beads uses Dolt as its sole storage backend -- a version-controlled SQL database that provides git-like semantics (branch, merge, diff, push, pull) natively at the database level.
By default, Dolt runs in embedded mode (in-process, no separate server). For multi-writer
setups (multiple agents, orchestrator), switch to server mode which connects to a
running dolt sql-server. See the Dolt Server Mode section below for details.
flowchart TD
subgraph DOLT["🗄️ Dolt Database"]
D[("embedded default: .beads/embeddeddolt/
server mode: .beads/dolt/
<i>Version-Controlled SQL</i>")]
end
subgraph REMOTE["🌐 Dolt Remotes"]
R[("DoltHub / S3 / GCS
<i>Sync & Backup</i>")]
end
D <-->|"bd dolt push/pull"| R
U((User)) -->|"bd create
bd update"| D
D -->|"bd list
bd show"| U
style DOLT fill:#2d5a27,stroke:#4a9c3e,color:#fff
style REMOTE fill:#1a4a6e,stroke:#3a8ac4,color:#fff
Recovery is straightforward: pull from a Dolt remote with bd dolt pull, or restore from a Dolt-native backup with bd backup restore.
</Info>
bd export produces JSONL for migration and interoperabilityThe database stores five kinds of records: issues (the beads themselves), dependencies (typed edges such as blocks, parent-child, related, and discovered-from), labels, comments, and events (the audit trail). What each means — and how bd ready computes the claimable frontier from them — is covered in How Beads Works.
Issue IDs are content-derived hashes (bd-a1b2) so that concurrent writers never collide and no central ID coordination is needed. See Hash-based IDs for the design and COLLISION_MATH for the birthday-paradox analysis of hash length vs collision probability.
Core fields on every issue, as stored in Dolt and emitted in bd export JSONL. Optional fields are omitted when empty.
| Field | Type | Description |
|---|---|---|
id | string | Unique hash ID (e.g., bd-a1b2) |
title | string | Issue title (required) |
description | string | Detailed description (optional) |
design | string | Design notes (optional) |
acceptance_criteria | string | Acceptance criteria (optional) |
notes | string | Additional notes (optional) |
status | string | open, in_progress, blocked, deferred, closed, pinned, hooked (defaults to open; extendable via the status.custom config key) |
priority | int | 0–4, where 0 = critical and 4 = backlog |
issue_type | string | bug, feature, task, epic, chore, decision, message, molecule, gate, spike, story, milestone (defaults to task) |
assignee | string | Assigned user/agent (optional) |
estimated_minutes | int | Time estimate in minutes (optional) |
created_at / updated_at | RFC3339 | Creation and last-modification times |
created_by | string | Who created the issue (optional) |
closed_at / close_reason | RFC3339 / string | Set when the issue is closed (optional) |
external_ref | string | External reference such as gh-9 or jira-ABC (optional) |
metadata | JSON | Arbitrary extension data — see Issue Metadata |
labels | []string | Tags attached to the issue (optional) |
dependencies | []Dependency | Typed edges to other issues (optional) |
comments | []Comment | Discussion thread (optional) |
Issues also carry workflow-layer field groups, among others: scheduling (due_at, defer_until), claim leasing (lease_expires_at, heartbeat_at), gates (await_type, await_id, timeout), and molecule/wisp fields (ephemeral, mol_type, bonded_from).
Internal fields — content_hash (a SHA-256 of the issue's canonical content, used for change detection), source_repo, and id_prefix — never appear in exports.
The schema is stable by default: prefer the metadata field for integration-, orchestrator-, or team-specific data before proposing new first-class fields. See the Project Charter's schema boundary.
User runs bd create
→ Dolt database updated
→ Auto-committed to Dolt history
User runs bd list
→ Dolt SQL query
→ Results returned immediately
User runs bd dolt push
→ Commits pushed to Dolt remote
User runs bd dolt pull
→ Remote commits fetched and merged
Dolt remotes can live on DoltHub, S3, GCS, a filesystem path, or your existing git remote — issue history rides under refs/dolt/data, separate from code branches. See Sync Concepts for the wire format and setup.
Cross-repo setups can also exchange beads peer-to-peer via federation. Ephemeral wisps are excluded from federation push by default, so execution traces never enter shared history.
When working across multiple machines or clones:
Always sync before switching machines
bd dolt push # Push changes before leaving
Pull before creating new issues
bd dolt pull # Pull changes first on new machine
bd create "New issue"
Avoid parallel edits - If two machines create issues simultaneously without syncing, Dolt's cell-level merge handles most conflicts automatically
See Sync Failures Recovery for data loss prevention in multi-machine workflows (Pattern A5/C3).
The Dolt server handles background synchronization and database operations:
.beads/: dolt-server.pid, dolt-server.log, and dolt-server.portAn opt-in shared server mode runs a single Dolt server at ~/.beads/shared-server/ for all projects, enabled with dolt.shared-server: true in config.yaml or BEADS_DOLT_SHARED_SERVER=1 — see Dolt Backend.
Embedded mode is the default (bd init with no flags): Dolt runs in-process, single-writer, with data at .beads/embeddeddolt/ — no server process and no separate Dolt install. Server mode is opt-in via bd init --server; the choice is persisted in .beads/metadata.json.
bd create "CI-generated issue"
bd dolt push
Beyond solo use, embedded mode is a natural fit for:
Prevention:
bd dolt stop) before switching between clonesSee Sync Failures Recovery for sync race condition troubleshooting (Pattern B2).
.beads/
├── embeddeddolt/ # Dolt database (embedded mode, default) — gitignored
├── dolt/ # Dolt database (server mode) — gitignored
├── dolt-server.pid # Server-mode runtime files (.pid, .log, .port) — gitignored
├── issues.jsonl # Passive JSONL export for viewers and interchange
├── metadata.json # Backend config — tracked in git
└── config.yaml # Project config (optional) — tracked in git
The database directory for your mode is the only thing holding issue data; everything else is configuration, runtime state, or a derived export. bd init writes a .beads/.gitignore that keeps the database and runtime files out of git.
Dolt's version control makes recovery straightforward:
bd dolt pullbd backup restore [path] --forceCreate backups with bd backup init (a filesystem path or DoltHub destination) and push them with bd backup sync. Dolt-native backups preserve full commit history; a JSONL export does not.
The following sequence resolves the majority of reported issues. For detailed procedures, see Recovery Runbooks.
bd dolt stop # Stop Dolt server (prevents race conditions)
git worktree prune # Clean orphaned worktrees
bd dolt pull # Pull from Dolt remote
bd dolt start # Restart server
cp -r .beads .beads.backupbd doctor --dry-run — shows what would be fixed without making changesbd doctor (no flags) — diagnostic only, no changes madebd doctor --fix — or bd doctor --fix -i to confirm each fix individuallyWhy caution? The --fix flag may remove dependencies it flags as circular, including valid parent-child relationships. Use --fix-child-parent only if you're certain the flagged deps are invalid.
Other diagnostic tools:
bd blocked — check which issues are blocked and whybd show <issue-id> — inspect a specific issue's state
</Warning>
See Recovery for specific procedures and Database Corruption Recovery for Dolt recovery steps.
Dolt is a version-controlled SQL database that provides git-like semantics natively. Unlike plain SQLite (binary merge conflicts) or JSONL (slow queries), Dolt gives you both fast SQL queries and proper merge semantics.
Beads is designed for offline-first, local-first development. The Dolt server runs locally -- no cloud dependency, no downtime, no vendor lock-in, and full functionality on airplanes or in restricted networks.
| Benefit | Trade-off |
|---|---|
| Works offline | No real-time collaboration |
| Version-controlled database | Server mode needed for concurrent writers |
| Cell-level merge | Requires initial setup |
| Local-first speed | Manual sync to remotes |
| SQL queries | Dolt storage engine dependency |
Beads is not suitable for:
For these use cases, consider GitHub Issues, Linear, or Jira.