Skip to main content

PostgreSQL (pgserve)

Genie embeds pgserve as a persistent database. One PostgreSQL instance runs per machine on port 19642, auto-started on demand. The connection is a lazy singleton — pgserve only starts when something actually needs the database.
Genie requires pgserve >=1.1.10 (bumped 2026-04-20).

How pgserve Works

Connection Details

Crash Recovery

On startup, killOrphanedPostgres() reads postmaster.pid from the data directory, verifies the PID is actually a postgres process (not a reused PID), then sends SIGTERM with a 5-second grace period before escalating to SIGKILL.

Schema Overview

The database schema is organized across 10 migration files covering core scheduling, task lifecycle, projects, state management, observability, boards, and an app registry.

Migration 001: Core Schema

Seven tables for the scheduler and observability (see Scheduler Architecture for how these tables drive the daemon loop):

Migration 002: Task Lifecycle

Eleven tables for the full task management system:

Migration 003: Projects

Project-level scoping for multi-repo task management. Adds the projects table with tasks.project_id foreign key.

Migration 004: Cleanup

Removes test pollution from production tables — deletes tasks with /tmp/* repo paths and messages with test* sender IDs. Cleans up orphaned test schemas.

Migration 005: PG State (replaces JSON files)

Five tables that replace the legacy JSON file-based state:

Migration 006: Schema Reconciliation

Fixes schema drift between seed-created tables and migration-created tables for the agents and agent_templates tables.

Migration 007: Observability

Two tables for full session observability: OTel structured events (cost, tokens, tool success/fail) flow into the existing audit_events table.

Migration 007b: Mailbox/Team Chat Reconciliation

Fixes production schema drift where 005_pg_state was recorded as applied but partially failed. Ensures mailbox and team_chat tables exist with correct schemas.

Migration 008: Boards

Two tables replacing task_types as the primary pipeline mechanism: Boards are more flexible than task types — each column can have its own gate type (human, agent, human+agent) and an associated action skill.

Migration 009: App Store

Unified item registry for the Genie ecosystem:

Built-in Task Pipeline

The software task type defines a 7-stage pipeline that maps to Genie skills:
Each stage has a gate type (human, agent, or human+agent) that determines whether the stage can auto-advance:

LISTEN/NOTIFY

PostgreSQL’s LISTEN/NOTIFY mechanism provides real-time event streaming without polling: The scheduler daemon subscribes to genie_trigger_due for real-time trigger notification, with a 30-second poll fallback as a safety net.

Task Service API

The task service (task-service.ts) provides CRUD operations scoped by repo_path:

Execution Locking

Tasks support atomic checkout via checkout_run_id and execution_locked_at fields. This prevents two agents from claiming the same task simultaneously:
The lock expires after checkout_timeout_ms (default: 600,000ms / 10 minutes).

Migration Runner

Migrations are loaded from src/db/migrations/ in lexicographic order. The _genie_migrations table tracks which migrations have been applied:
Each migration runs in its own transaction. If a migration fails, subsequent migrations are skipped and the error is thrown.