grite-daemon
High-performance background daemon for Grite — eliminates per-command startup overhead and enables concurrent, multi-process access to the issue database.
grite-daemon is the optional but highly recommended background service that powers the Grite CLI. It keeps materialized views warm in memory, handles concurrent IPC requests, and manages the lifecycle of per-actor databases. It is not required for correctness — the CLI works standalone — but it transforms Grite from a fast tool into a lightning-fast one.
Why a Daemon?
Every time the grite CLI runs, it must:
- Open the sled database
- Check if the materialized view is stale
- Replay new events from the git WAL into the view
- Execute the query
- Close the database
For simple queries, steps 1-3 dominate the runtime. With the daemon, these happen once. Subsequent commands are pure query execution against an in-memory cache.
Performance Impact
| Scenario | Without Daemon | With Daemon | Speedup |
|---|---|---|---|
First issue list |
~150ms | ~150ms | 1x |
Second issue list |
~150ms | ~5ms | 30x |
50 concurrent issue list calls |
Serialized, ~7s total | Parallel, ~200ms total | 35x |
| Agent batch query (100 issues) | ~2s | ~50ms | 40x |
The daemon pays for itself on the second command and provides massive speedups for agent workloads that issue hundreds of queries per session.
What the Daemon Does
Keep Databases Warm
The daemon opens each actor's sled database on first access and keeps it open. This eliminates the open/close overhead on every CLI invocation and allows the operating system's page cache to work effectively.
Handle Concurrent Requests
Multiple CLI processes can connect to the daemon simultaneously over Unix domain sockets. The daemon routes requests to a pool of async workers, enabling parallel reads while serializing writes to maintain consistency.
Auto-Spawn and Idle Shutdown
The daemon is completely hands-off:
- Auto-spawn: The first CLI command starts the daemon automatically if it is not running.
- Idle shutdown: The daemon stops automatically after a configurable period of inactivity (default: 5 minutes). No resource leaks. No manual cleanup.
- Graceful shutdown: Responds to
SIGINTandSIGTERMby finishing in-flight requests and flushing state before exiting.
Database Lock Coordination
The daemon uses filesystem-level locking (flock) to prevent database corruption from concurrent access, even when multiple processes try to open the same sled database. If the daemon is running, it holds the lock. If the CLI runs in standalone mode, it acquires the lock directly.
Pub/Sub Infrastructure
The daemon architecture supports pub/sub notifications (enabled in future releases), allowing real-time issue change notifications for long-running agent sessions or editor integrations.
Architecture
+-----------------------------------------------------------+
| grite-daemon |
| |
| +----------------+ +-----------------------------+ |
| | Supervisor | --> | Unix Domain Socket Server | |
| | | | (bind, accept, route) | |
| +----------------+ +-----------------------------+ |
| | | |
| v v |
| +----------------+ +-----------------------------+ |
| | Signal Handler | | Worker Pool | |
| | SIGINT/SIGTERM | | (async tokio tasks) | |
| +----------------+ +-----------------------------+ |
| | |
| v |
| +-------------------+ |
| | Per-Actor Stores | |
| | (sled databases) | |
| +-------------------+ |
+-----------------------------------------------------------+
^
| Unix domain socket (rkyv zero-copy)
v
+-----------------------------------------------------------+
| grite (CLI) |
+-----------------------------------------------------------+
Components
Supervisor— Top-level lifecycle manager. Binds the socket, accepts connections, routes messages to workers, and coordinates graceful shutdown.Worker— Per-request async worker that executes CLI operations. Workers are spawned from a tokio task pool and run operations inspawn_blockingfor CPU-intensive work.WorkerMessage— Command envelope that carries the operation type, arguments, and actor context from the CLI to the worker.shutdown_signal/setup_signal_handlers— Cross-platform signal handling forSIGINTandSIGTERM. Ensures the daemon finishes in-flight requests before exiting.
IPC Protocol
The daemon communicates with the CLI over Unix domain sockets using libgrite-ipc:
- Serialization:
rkyvfor zero-copy deserialization. Messages are laid out in memory exactly as they are received, with no parsing overhead. - Message types:
IpcCommandvariants for every CLI operation (issue create, list, sync, lock, etc.), andIpcResponsevariants for success, error, and streaming results. - Socket path: Deterministic path based on the repository and actor ID, discovered via the daemon lock file.
Usage
As an End User
You rarely need to interact with the daemon directly. The CLI handles it automatically:
# The daemon starts automatically on first use
# It shuts down automatically after idle timeout
# (configurable, default 300 seconds)
# Manual control when needed
As a Library
Embed the daemon in your own Rust application:
use Supervisor;
use Duration;
async
Configuration
Daemon behavior is controlled through the CLI and configuration files:
| Option | Default | Description |
|---|---|---|
--idle-timeout |
300s | Shutdown after this many seconds of inactivity |
--socket-path |
Auto | Unix domain socket path (auto-detected from repo) |
Configuration can also be set in .git/grite/config.toml:
[]
= 300
Performance Characteristics
Throughput
- Request handling: 1,000+ IPC requests per second
- Concurrent clients: 50+ simultaneous CLI processes
- Worker pool: Auto-scaled based on CPU cores
Resource Usage
- Idle memory: ~10MB RSS (no open databases)
- Active memory: ~30MB RSS per actor database (sled cache + materialized view)
- CPU: Near-zero when idle; spikes during view rebuilds
Startup Time
- Cold start: ~100ms (open databases, replay WAL delta)
- Warm start: ~5ms (database already open, minimal delta)
Reliability
Crash Safety
If the daemon crashes, no data is lost. The WAL lives in git refs, and the materialized view can be rebuilt at any time. The CLI falls back to standalone mode automatically.
Zombie Process Prevention
The daemon writes a PID file and heartbeat. If a stale PID file is detected (daemon died without cleanup), it is overwritten on the next startup.
Graceful Degradation
If the daemon socket is unavailable or corrupted, the CLI transparently falls back to direct database access. The user never sees an error — just slightly higher latency.
See Also
- Grite Repository — Main project and documentation
- grite — The CLI frontend that uses this daemon
- libgrite-ipc — IPC protocol and client library
- docs.rs/grite-daemon — Rust API documentation
License
MIT License — see LICENSE for details.