Memory governance: a cache that respects its container

CROWKIS_MEMORY_LIMIT means what it says, no GC mood swings, no mystery RSS, eviction that engages before the kernel has opinions.

The classic cache-in-a-container failure: memory drifts up, the limit is a suggestion the runtime's garbage collector negotiates with, and one day the OOM killer adjudicates. Post-mortems blame the limit, the workload, or the moon. The real culprit is a runtime that can't make memory promises.

Rust can make them, and Crowkis does: CROWKIS_MEMORY_LIMIT bounds the process, CROWKIS_BLOCK_CACHE_BYTES bounds the read accelerator inside it, and the memtable's 64MB flush threshold bounds write buffering. No collector defers reclamation to a more convenient mood; allocation discipline is structural.

flowchart LR
  LOOP["runaway agent loop"] --> KEY["virtual API key<br/>budget + TPM/RPM limits"]
  KEY -- "under budget" --> CK["crowkis → provider"]
  KEY -- "wall hit" --> STOP["blocked · alert fired"]
  style STOP fill:#fbe9e8,stroke:#d62221,stroke-width:2.5px
Figure 1. the budget wall, enforced locally The wall is enforced before the invoice, not discovered on it.

Pressure response is graduated rather than catastrophic: as usage approaches bounds, smart eviction engages, shedding entries by the recency/frequency/isolation/cost score, cheapest-to-rebuild first, so the cache slims itself economically long before the kernel gets involved. The dashboard shows the pressure curve, so capacity planning is a graph, not a guess.

The bottom line

The operational payoff is trust in your own configs: requests and limits you write are bounds that hold, sizing math survives contact with production, and the OOM-killer chapter of your runbook quietly goes unused.