9.4 Resource Exhaustion
9.4.1 Memory #
If the out-of-memory killer takes eventd, it is treated exactly as a crash (§8.5): the databases are consistent, the ring buffers are untouched, peinit restarts the daemon, and the gap is recorded.
The principal long-lived memory consumers are:
| Consumer | Proportional to | Bounded by |
|---|---|---|
| Series cache | distinct metric series held in memory | MetricSeriesCacheSize (§5.3) |
| Event-type and log-origin intern sets | distinct committed identifiers not yet cleaned from active catalogues | catalogue cardinality; no independent memory setting (§3.1, §4.2) |
| Adaptive index counters | distinct event fields queried | the event query surface |
| SQLite page caches | connections and active indexes | per-connection configuration (§C) |
| Event handoff channels | occupied slots and copied event bytes | startup-fixed internal slot and byte limits (§2.3) |
The handoff limits do not follow live MaxBatchSize changes.
The
channels are small scheduling handoffs; KMES remains the real event
backlog.
High-cardinality producers are the likely surprise. The series cache
cannot grow past its limit, but the series table can grow and make it
thrash on the thread that also drains the metric socket (§5.3).
Identifier intern sets intentionally trade memory for zero catalogue work
on known-name ingestion. The default 1 GiB metric retention ceiling and
low-priority orphan cleanup bound persistent growth indirectly, but do
not bound the number of active series between retention passes.
9.4.2 Query slots #
Reaching MaxConcurrentQueries, MaxStreamingQueries or
MaxQueriesPerUser rejects new queries with an error rather than
queueing them (§6.5).
The per-user bound keeps one caller from occupying every slot; several
callers together, or SYSTEM, still can.
Ingestion is unaffected, because queries and ingestion are separate channels and separate threads. That separation is what makes query-side exhaustion an inconvenience rather than data loss.
9.4.3 Descriptors #
An event query opens a read-only connection per shard database, and each connection holds one or two file descriptors (§6.4). Many historical shards multiplied by many concurrent queries reaches a process limit faster than anything else eventd does.
Where eventd cannot allocate what an admitted query needs, it fails that query rather than blocking a writer or exceeding its own limit (§6.1).
9.4.4 Writer stalls #
Two things stall a writer thread briefly, and both are bounded by design.
An index build in progress. Drain threads detect rising write
pressure and signal cancellation; the writer aborts the CREATE INDEX,
SQLite rolls back the partial index, and event writing resumes
immediately (§3.4).
A writer-owned maintenance command. Retention and adaptive-index maintenance execute only as bounded, low-priority commands at transaction boundaries. Ingestion wins before the next command; there is no competing read-write connection or writer mutex (§3.6).
Neither stall loses anything by itself. Both contribute to ring buffer pressure, and prolonged enough, both end at §9.1.