Tuning
Most workloads run well on defaults. Reach for these knobs when you’ve measured a specific bottleneck.
When latency is the problem
-
Profile per-stage:
Terminal window export NAMIDB_PROFILE_DUMP=1This pinpoints whether time is in parse, lower, optimise, or execute.
-
EXPLAIN VERBOSEto see the plan and selectivity estimates. -
If execute dominates and the plan looks reasonable, try factorization:
Terminal window export NAMIDB_FACTORIZE=1Big win on path-heavy queries (IC09, IC11) where intermediate results explode under non-factorized evaluation.
When memory is the problem
Cap the caches:
export NAMIDB_ADJACENCY_BUDGET_MB=256export NAMIDB_NODE_CACHE_BUDGET_MB=256export NAMIDB_SST_CACHE_BUDGET_MB=512All three are eviction-bounded — never exceed the budget.
Or disable one entirely:
export NAMIDB_ADJACENCY=offexport NAMIDB_NODE_CACHE=offFor the embedded use case inside small containers / Lambdas, a common profile is “small NodeCache, no SstCache, full AdjacencyCache”.
When write throughput is the problem
-
Bulk-stage instead of per-row
CREATE— usemerge_nodes/merge_edgesfrom Python, orupsert_node/upsert_edgefrom Rust. These amortise a singlecommit_batch()over thousands of rows. -
Increase flush interval on
namidb-serverif you’re doing burst-write workloads:Terminal window --flush-interval 5mLarger memtables → fewer L0 SSTs → less compaction work.
-
Shard by namespace. Each namespace has one writer. Two unrelated workloads on two namespaces double your write throughput.
When cold-read latency is the problem
This is dominated by SST fetch from the bucket. Options:
- Move the daemon closer to the bucket. Same region, same VPC.
- Pre-warm with a one-time query that touches the working set — subsequent queries hit the SST cache.
- Bump
NAMIDB_SST_CACHE_BUDGET_MBso the working set fits.