Skip to content

fix(config): warn when a pinned DuckDB budget cannot fit the machine - #261

Merged
vishr merged 1 commit into
mainfrom
fix/validate-pinned-duckdb-memory
Sep 20, 2026
Merged

vishr merged 1 commit into
mainfrom
fix/validate-pinned-duckdb-memory

Conversation

@vishr

@vishr vishr commented Sep 20, 2026

Copy link
Copy Markdown
Member

Fourth item of #254.

Problem

Setting storage.duckdb.memory skips detection entirely — resolveSizing only fills a value that is empty — so nothing ever compared the figure to the machine it would run on.

Both production deployments pin 4GB on 8 GiB hosts and have been OOM-killed repeatedly. The startup log recorded the pin without comment:

"duckdb_memory":"4GB","duckdb_memory_auto":false,
"detected_memory_bytes":0,"memory_source":""

Every field that could have flagged the mismatch reads zero, because pinning the value is what stopped them being populated.

Change

DuckDB's budget is not the process's budget — the Go heap, the ingest appender and compaction's merges all allocate on top of it. That is why duckDBMemoryPercent leaves 40% of the machine alone when sizing itself. A pinned value is now judged by the same standard, and an unparseable one is called out rather than handed to DuckDB to interpret.

It warns, it does not refuse. An operator who has measured their workload may legitimately know better than the default share, and failing startup on a configuration that has been running would trade a survivable problem for an outage.

Adds parseByteSize for the forms an operator is likely to write: a bare count, or a decimal with a GB/GiB/MB/MiB/KB/KiB suffix.

Correction to #254

The issue claims applyMemoryHeadroom is "effectively dead code". That is wrong, and I wrote it. I took it from a review without checking the branch myself.

resolveDuckDBMemory returns "" when detection declines, so DuckDBMemory stays empty on that path, the cfg.DuckDBMemory == "" guard at duck.go:267 opens, and applyMemoryHeadroom clamps DuckDB's own cgroup-aware default. That is exactly the case its comment describes. This PR leaves it alone; I am commenting the correction on the issue.

Tests

  • TestPinnedMemoryConcern — table across pins inside the automatic share, at half the machine, above the share, above the machine, unparseable, absent, and an undetectable machine that cannot be judged either way.
  • TestParseByteSize — the suffix forms, a bare count, a decimal, surrounding whitespace, and the negative and unparseable cases.

Both written first and verified failing.

One gap, stated plainly: the slog.Warn call site itself is not covered. The decision function is fully tested; the wiring is a single call to it, and there is no log-capture helper in this package to lean on.

just check passes.

Setting storage.duckdb.memory skips detection entirely -- resolveSizing
only fills a value that is empty -- so nothing ever compared the figure to
the machine it would run on. Both production deployments pinned 4GB on
8 GiB hosts and were OOM-killed repeatedly, and the startup log recorded
the pin without comment: duckdb_memory 4GB, detected_memory_bytes 0,
memory_source "".

DuckDB's budget is not the process's budget. The Go heap, the ingest
appender and compaction's merges all allocate on top of it, which is why
duckDBMemoryPercent leaves 40% of the machine alone when it sizes itself.
A pinned value is now judged by that same standard, and an unparseable one
is called out rather than passed through to DuckDB to interpret.

This warns rather than refuses. An operator who has measured their
workload may legitimately know better than the default share, and failing
startup on a configuration that has been running would trade a survivable
problem for an outage.

Adds parseByteSize for the forms an operator is likely to write -- a bare
count, or a decimal with a GB/GiB/MB/MiB/KB/KiB suffix.

Note on applyMemoryHeadroom, which this does not touch: it is reachable,
contrary to what the ingest-memory issue currently claims. resolveSizing
leaves DuckDBMemory empty when detection declines, and on that path
DuckDB keeps its own cgroup-aware default and applyMemoryHeadroom clamps
it -- exactly the case its comment describes. The issue will be corrected.
@vishr
vishr merged commit 1199e15 into main Sep 20, 2026
8 checks passed
@vishr
vishr deleted the fix/validate-pinned-duckdb-memory branch September 20, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant