July 3, 2026

Disk & Database Diet

Database: 427GB → 305GB

The production database crossed 427GB, with sailing_prices alone at 378GB. A full footprint analysis produced a tiered roadmap; Tier 1 landed today:

  • Dropped an 82GB index with zero lifetime scans -- built long ago for a trends query that never shipped in that form.
  • Stopped storing raw API responses on personalized package prices -- 39GB of compressed JSON nobody ever read back, and the raw-response observatory already logs the same responses independently. The column was nulled in batches and kept for rollback safety.

Post-VACUUM actuals: 305GB, a 122GB reclaim. Tier 2 (a change-only price ledger -- 98.7% of hourly rows are unchanged from the previous hour) remains on the roadmap.

Disk: Three Compounding Leaks

  • The Silversea day-dir leak. The cache archiver only removed an expired day directory once it was empty, but Silversea writes sitemap and marker files the archiver didn't handle -- so its day dirs never emptied and ~4 months of them piled up while every other line self-pruned. Sitemaps are now archived as real data and leftover marker files are cleaned before the prune (guarded so a failed upload never deletes un-archived data).
  • MSC's cache appetite. Once the Akamai bypass made MSC scrapes actually succeed, its cache started growing ~6GB/day. MSC now keeps zero days of cache with intra-day cleanup -- safe because cache lookups are hour-prefixed, so files older than two hours can never be hits again.
  • The no-op archive loop. With baseline disk usage stuck above the 70% emergency threshold, the scheduler spawned an emergency archive every minute for 21 hours, each run freeing zero bytes because everything remaining was within retention. Emergency archives now carry a 30-minute cooldown.