---
sidebar_position: 1
title: Architecture Overview
description: Understanding Beads' three-layer data model
---
# Architecture Overview
This document explains how Beads' three-layer architecture works: Git, JSONL, and SQLite.
## The Three Layers
Beads uses a layered architecture where each layer serves a specific purpose:
```mermaid
flowchart TD
subgraph GIT["🗂️ Layer 1: Git Repository"]
G[(".beads/*.jsonl
Historical Source of Truth")]
end
subgraph JSONL["đź“„ Layer 2: JSONL Files"]
J[("issues.jsonl
Operational Source of Truth")]
end
subgraph SQL["⚡ Layer 3: SQLite"]
D[("beads.db
Fast Queries / Derived State")]
end
G <-->|"bd sync"| J
J -->|"rebuild"| D
D -->|"append"| J
U((👤 User)) -->|"bd create
bd update"| D
D -->|"bd list
bd show"| U
style GIT fill:#2d5a27,stroke:#4a9c3e,color:#fff
style JSONL fill:#1a4a6e,stroke:#3a8ac4,color:#fff
style SQL fill:#6b3a6b,stroke:#a45ea4,color:#fff
```
:::info Historical vs Operational Truth
**Git** is the *historical* source of truth—commits preserve the full history of your issues and can be recovered from any point in time.
**JSONL** is the *operational* source of truth—when recovering from database corruption, Beads rebuilds SQLite from JSONL files, not directly from Git commits.
This layered model enables recovery: if SQLite is corrupted but JSONL is intact, run `bd sync --import-only` to rebuild. If JSONL is corrupted, recover it from Git history first.
:::
### Layer 1: Git Repository
Git is the *historical* source of truth. All issue data lives in the repository alongside your code, with full history preserved in commits.
**Why Git?**
- Issues travel with the code
- No external service dependency
- Full history via Git log (recover any point in time)
- Works offline
- Enables multi-machine and multi-agent workflows
### Layer 2: JSONL Files
JSONL (JSON Lines) files store issue data in an append-only format. This is the *operational* source of truth—SQLite databases are rebuilt from JSONL.
**Location:** `.beads/*.jsonl`
**Why JSONL?**
- Human-readable and inspectable
- Git-mergeable (append-only reduces conflicts)
- Portable across systems
- Can be recovered from Git history
- **Recovery source**: `bd sync --import-only` rebuilds SQLite from JSONL
### Layer 3: SQLite Database
SQLite provides fast local queries without network latency. This is *derived state*—it can always be rebuilt from JSONL.
**Location:** `.beads/beads.db`
**Why SQLite?**
- Instant queries (no network)
- Complex filtering and sorting
- Derived from JSONL (always rebuildable)
- Safe to delete and rebuild: `rm .beads/beads.db* && bd sync --import-only`
## Data Flow
### Write Path
```text
User runs bd create
→ SQLite updated
→ JSONL appended
→ Git commit (on sync)
```
### Read Path
```text
User runs bd list
→ SQLite queried
→ Results returned immediately
```
### Sync Path
```text
User runs bd sync
→ Git pull
→ JSONL merged
→ SQLite rebuilt if needed
→ Git push
```
### Sync Modes
Beads provides specialized sync modes for different recovery scenarios:
#### Standard Sync
```bash
bd sync
```
Normal bidirectional sync: pulls remote changes, merges JSONL, rebuilds SQLite if needed, pushes local changes.
#### Import-Only Mode
```bash
bd sync --import-only
```
Rebuilds the SQLite database from JSONL without pushing changes. Use this when:
- SQLite is corrupted or missing
- Recovering from a fresh clone
- Rebuilding after database migration issues
This is the safest recovery option when JSONL is intact.
#### Force Rebuild Mode
```bash
bd sync --force-rebuild
```
Forces complete SQLite rebuild from JSONL, discarding any SQLite-only state. Use with caution:
- More aggressive than `--import-only`
- May lose any uncommitted database state
- Recommended when standard sync fails repeatedly
### Multi-Machine Sync Considerations
When working across multiple machines or clones:
1. **Always sync before switching machines**
```bash
bd sync # Push changes before leaving
```
2. **Pull before creating new issues**
```bash
bd sync # Pull changes first on new machine
bd create "New issue"
```
3. **Avoid parallel edits** - If two machines create issues simultaneously without syncing, conflicts may occur
See [Sync Failures Recovery](/recovery/sync-failures) for data loss prevention in multi-machine workflows (Pattern A5/C3).
## The Daemon
The Beads daemon (`bd daemon`) handles background synchronization:
- Watches for file changes
- Triggers sync on changes
- Keeps SQLite in sync with JSONL
- Manages lock files
:::tip
The daemon is optional but recommended for multi-agent workflows.
:::
### Running Without the Daemon
For CI/CD pipelines, containers, and single-use scenarios, run commands without spawning a daemon:
```bash
bd --no-daemon create "CI-generated issue"
bd --no-daemon sync
```
**When to use `--no-daemon`:**
- CI/CD pipelines (Jenkins, GitHub Actions)
- Docker containers
- Ephemeral environments
- Scripts that should not leave background processes
- Debugging daemon-related issues
### Daemon in Multi-Clone Scenarios
:::warning Race Conditions in Multi-Clone Workflows
When multiple git clones of the same repository run daemons simultaneously, race conditions can occur during push/pull operations. This is particularly common in:
- Multi-agent AI workflows (multiple Claude/GPT instances)
- Developer workstations with multiple checkouts
- Worktree-based development workflows
**Prevention:**
1. Use `bd daemons killall` before switching between clones
2. Ensure only one clone's daemon is active at a time
3. Consider `--no-daemon` mode for automated workflows
:::
See [Sync Failures Recovery](/recovery/sync-failures) for daemon race condition troubleshooting (Pattern B2).
## Recovery Model
The three-layer architecture makes recovery straightforward because each layer can rebuild from the one above it:
1. **Lost SQLite?** → Rebuild from JSONL: `bd sync --import-only`
2. **Lost JSONL?** → Recover from Git history: `git checkout HEAD~1 -- .beads/issues.jsonl`
3. **Conflicts?** → Git merge, then rebuild
### Universal Recovery Sequence
The following sequence demonstrates how the architecture enables quick recovery. For detailed procedures, see [Recovery Runbooks](/recovery).
This sequence resolves the majority of reported issues:
```bash
bd daemons killall # Stop daemons (prevents race conditions)
git worktree prune # Clean orphaned worktrees
rm .beads/beads.db* # Remove potentially corrupted database
bd sync --import-only # Rebuild from JSONL source of truth
```
:::danger Never Use `bd doctor --fix`
Analysis of 54 GitHub issues revealed that `bd doctor --fix` frequently causes **more damage** than the original problem:
- Deletes "circular" dependencies that are actually valid parent-child relationships
- False positive detection removes legitimate issue links
- Recovery after `--fix` is harder than recovery from the original issue
**Safe alternatives:**
- `bd doctor` — Diagnostic only, no changes made
- `bd blocked` — Check which issues are blocked and why
- `bd show ` — Inspect a specific issue's state
If `bd doctor` reports problems, investigate each one manually before taking any action.
:::
See [Recovery](/recovery) for specific procedures and [Database Corruption Recovery](/recovery/database-corruption) for `bd doctor --fix` recovery (Pattern D4).
## Design Decisions
### Why not just SQLite?
SQLite alone doesn't travel with Git or merge well across branches. Binary database files create merge conflicts that are nearly impossible to resolve.
### Why not just JSONL?
JSONL is slow for complex queries. Scanning thousands of lines for filtering and sorting is inefficient. SQLite provides indexed lookups in milliseconds.
### Why append-only JSONL?
Append-only format minimizes Git merge conflicts. When two branches add issues, Git can cleanly merge by concatenating the additions. Edit operations append new records rather than modifying existing lines.
### Why not a server?
Beads is designed for offline-first, local-first development. No server means no downtime, no latency, no vendor lock-in, and full functionality on airplanes or in restricted networks.
### Trade-offs
| Benefit | Trade-off |
|---------|-----------|
| Works offline | No real-time collaboration |
| Git-native history | Requires Git knowledge |
| No server dependency | No web UI or mobile app |
| Local-first speed | Manual sync required |
| Append-only merging | JSONL files grow over time |
### When NOT to use Beads
Beads is not suitable for:
- **Large teams (10+)** — Git-based sync doesn't scale well for high-frequency concurrent edits
- **Non-developers** — Requires Git and command-line familiarity
- **Real-time collaboration** — No live updates; requires explicit sync
- **Cross-repository tracking** — Issues are scoped to a single repository
- **Rich media attachments** — Designed for text-based issue tracking
For these use cases, consider GitHub Issues, Linear, or Jira.
## Related Documentation
- [Recovery Runbooks](/recovery) — Step-by-step procedures for common issues
- [CLI Reference](/cli-reference) — Complete command documentation
- [Getting Started](/) — Installation and first steps