---
id: w8/m4/t004
title: Wire compaction into a periodic loop + env-tunable hot-window knob
worker: worker8
status: done
estimate: 35m
depends_on: [w8/m4/t003]
---

## Objective

Run the t003 compaction routine on a periodic (daily) cadence, reusing `usage.Service`'s existing loop-lifecycle pattern (`RunWithInterval`), gated by the same `BEX_CP_DB_URI` availability check. Add an env var for the hot-window length.

## Context

- `usage.Service.Run`/`RunWithInterval` (`service.go:159`) is the existing loop pattern — add a second, lower-frequency tick for compaction rather than inventing a new loop mechanism.
- New env var, e.g. `BEX_USAGE_RETENTION_MONTHS` (default from t001's chosen value) — must be documented in `CLAUDE.md`'s env table and mirrored in `.env.example`/`.env.template` per repo rule.

## Steps

1. Add a daily compaction tick alongside the existing hourly rollup tick in `usage.Service.Run`.
2. Add `BEX_USAGE_RETENTION_MONTHS` env var, threaded into the compaction call as the hot-window length.
3. Update `CLAUDE.md`'s environment-variables table + `.env.example`/`.env.template`.

## Files

- `lego/backend/internal/usage/service.go`
- `CLAUDE.md`
- `.env.example`, `.env.template`

## Acceptance criteria

- [ ] Compaction runs automatically once per day when the service loop is active, without needing a manual trigger.
- [ ] `BEX_USAGE_RETENTION_MONTHS` changes the hot-window length observably.
- [ ] `.env.example`/`.env.template` stay in sync with the new var (repo rule).

## Out of scope

- A standalone k8s CronJob (the in-process loop is sufficient at this scale; revisit only if bex-api's own restart cadence becomes a problem for compaction reliability).
