<aside> 📋

Status: proposal for public review. No code, schema or deployment has been changed by this document. Each item becomes its own pull request, reviewed separately.

Baseline: source at commit 3e0deda on bansalayush247/fedimint-observer (master), and read-only measurements on a copy of the production database (about 24 GB, 17 federations, PostgreSQL 18).

Evidence labels: Measured = EXPLAIN (ANALYZE, BUFFERS) or catalog queries on the database copy, run on a laptop with default settings (absolute times differ from the server; row counts and relative costs transfer). Verified = read in the source at the cited file and line. Observed = seen on the running production service. Assumption = not yet measured.

How to review: comment directly on any paragraph or table row. Section 14 lists the questions where outside input matters most.

Builds on: the maintainers' approved modularization design for issue #8; section 0.1 explains how this review fits it.

Not in this draft: some request-hardening details are left out until the fixes ship; maintainers have the full version.

</aside>

0. Summary

Fedimint Observer is one Rust binary (fmo_server, about 5,700 lines in 18 files) plus a shared types crate and a React frontend. It polls the federations it tracks, stores sessions, transactions, guardian health, gateway registrations and Nostr events in PostgreSQL, and serves a REST API behind Nginx.

The code structure is set by the maintainers' approved modularization design (section 0.1): a core library plus one crate per fedimint module, built into one binary. Within that design, the evidence supports incrementally maintained tables replacing per-request and per-minute full recomputation. No new infrastructure is justified. Redis, TimescaleDB, ClickHouse, message brokers and microservices were each evaluated and rejected; section 4.7 states the condition that would change each verdict.

The five findings that matter most

  1. The session_times materialized view is rebuilt in full every 60 seconds. Measured at 5.7 s per rebuild on the laptop copy and observed at about 30 s per rebuild in production, so the database spends a large share of a core on it continuously. A one-line interval change removes 90% of that cost; an incremental table removes all of it (section 7.1).
  2. The transaction histogram endpoint recomputes a federation's full history on every uncached detail-page view. Measured 5.5 s warm for the largest federation, scanning 3.1 million input rows with an on-disk sort (section 7.2).
  3. guardian_health is 13 GB of the 24 GB database and grows about 50 MB per day with no retention. Only one field of its 543-byte status JSON is ever read (section 7.4).
  4. Ingestion is coupled to the esplora API (mempool.space). A foreign key on block heights plus an unbounded HTTP retry inside an open database transaction mean an esplora outage stalls session sync for every federation (section 1.4).
  5. Seven verified correctness defects, including an admin backfill that never commits, migration files whose inner COMMIT breaks the outer transaction, and decoding panics that silently stop a federation's sync (section 10).

Direction already agreed by the maintainers

0.1 The approved design, and what this review adds

The maintainers approved a modularization design for issue #8 on 2026-08-02 (design spec). This review builds on it: the design sets the structure, and this page adds production measurements, fixes for the live service until the rebuild ships, and proposals for gaps in the design.

The approved design in brief