Skip to content

Implementations

BigBrotr’s three-layer architecture enables multiple deployment configurations from the same codebase. Two implementations are provided out of the box, each optimized for different use cases.

The default implementation with complete event storage and all features enabled.

FeatureValue
Event StorageFull (tags, content, signatures)
Tor SupportEnabled
Concurrency10 parallel connections, 10 worker processes
PostgreSQL Port5432
PGBouncer Port6432
Tor Port9050

Best for:

  • Complete Nostr archiving
  • Research and analytics requiring full event data
  • Applications needing tag-based queries
  • Long-term event preservation
Terminal window
cd implementations/bigbrotr
docker-compose up -d

A lightweight implementation that indexes all events but omits storage-heavy fields (tags, content) to minimize disk usage.

FeatureValue
Event StorageEssential metadata (id, pubkey, created_at, kind, sig)
Omitted Fieldstags, tagvalues, content
Disk Savings~60% compared to BigBrotr
Tor SupportDisabled by default
Concurrency5 parallel connections
PostgreSQL Port5433
PGBouncer Port6433
Tor Port9051

Best for:

  • Event indexing without content storage
  • Analytics on event metadata (authors, kinds, timestamps)
  • Resource-constrained environments
  • When you don’t need tag-based queries or event content
  • Running alongside BigBrotr on the same machine
Terminal window
cd implementations/lilbrotr
docker-compose up -d

The key difference is in the events table:

CREATE TABLE events (
id BYTEA PRIMARY KEY,
pubkey BYTEA NOT NULL,
created_at BIGINT NOT NULL,
kind INTEGER NOT NULL,
tags JSONB NOT NULL, -- Stored
tagvalues TEXT[] GENERATED ALWAYS AS
(tags_to_tagvalues(tags)) STORED, -- Indexed for queries
content TEXT NOT NULL, -- Stored
sig BYTEA NOT NULL
);
CREATE TABLE events (
id BYTEA PRIMARY KEY,
pubkey BYTEA NOT NULL,
created_at BIGINT NOT NULL,
kind INTEGER NOT NULL,
-- tags NOT stored (saves ~40% disk space)
-- tagvalues NOT generated (no tag-based queries)
-- content NOT stored (saves ~20% disk space)
sig BYTEA NOT NULL
);

LilBrotr still indexes all events from all relays - it simply stores less data per event. You can still query by author, kind, timestamp, and track event distribution across relays.

Both implementations can run on the same machine using different ports:

Terminal window
# Start BigBrotr
cd implementations/bigbrotr
docker-compose up -d
# Start LilBrotr (in another terminal)
cd implementations/lilbrotr
docker-compose up -d

Access databases:

Terminal window
# BigBrotr
psql -h localhost -p 5432 -U admin -d bigbrotr
# LilBrotr
psql -h localhost -p 5433 -U admin -d lilbrotr

You can create your own implementation for specific use cases:

Terminal window
cp -r implementations/bigbrotr implementations/myimpl
cd implementations/myimpl

Edit YAML files in yaml/ directory:

yaml/services/synchronizer.yaml
tor:
enabled: false # Disable Tor
filter:
kinds: [0, 1, 3, 6, 7] # Only sync specific event kinds
concurrency:
max_parallel: 3 # Lower concurrency
max_processes: 2 # Fewer workers

Edit postgres/init/02_tables.sql for custom storage:

-- Only store metadata events (kinds 0, 3, 10002)
ALTER TABLE events ADD CONSTRAINT events_kind_check
CHECK (kind IN (0, 3, 10002));

Edit docker-compose.yaml to avoid port conflicts:

services:
postgres:
ports:
- "5434:5432" # Different port
pgbouncer:
ports:
- "6434:5432"
Terminal window
cp .env.example .env
nano .env # Set DB_PASSWORD
docker-compose up -d

Store only specific event types like profiles and contact lists:

yaml/services/synchronizer.yaml
filter:
kinds: [0, 3, 10002] # Profile, contacts, relay list

Monitor and sync from a single relay:

yaml/services/synchronizer.yaml
source:
from_database: false
static_relays:
- "wss://relay.damus.io"

Store only relay metadata, no events:

-- postgres/init/02_tables.sql
-- Remove or empty the events table
-- Keep only relays, relay_metadata, nip11, nip66

Use region-specific seed relays:

data/seed_relays.txt
wss://relay.example.eu
wss://relay.example.de
wss://relay.example.fr

Each implementation contains:

implementations/myimpl/
├── yaml/
│ ├── core/
│ │ └── brotr.yaml # Database connection settings
│ └── services/
│ ├── initializer.yaml # Schema verification, seed file
│ ├── finder.yaml # API sources, intervals
│ ├── monitor.yaml # Health check settings
│ └── synchronizer.yaml # Event sync configuration
├── postgres/
│ └── init/ # SQL schema files (00-99)
│ ├── 01_extensions.sql
│ ├── 02_tables.sql
│ ├── 03_indexes.sql
│ ├── 04_functions.sql
│ └── 05_views.sql
├── pgbouncer/
│ └── pgbouncer.ini # Connection pooler config
├── data/
│ └── seed_relays.txt # Initial relay URLs
├── docker-compose.yaml
├── Dockerfile
└── .env.example

The core (src/core/) and service (src/services/) layers remain unchanged across all implementations. Only configuration differs.