---
title: "Per-Request Memory Hygiene: Why HeliosDB Lite Stays Steady Under Sustained Load"
description: "Lite v3.6.0 (and Full v7.4.0) scope each statement's scratch memory to the request. What that changes for operators under sustained multi-tenant load, and how to watch per-query arena bytes in `helios_query_stats`."
date: 2026-05-26
updated: 2026-05-26
tag: "Engineering"
canonical: https://www.heliosdb.com/blog/lite-per-request-memory-hygiene.html
---

# Per-Request Memory Hygiene: Why HeliosDB Lite Stays Steady Under Sustained Load

A SQL engine that runs for a month under sustained multi-tenant traffic looks very different from one running a microbenchmark for an hour. Long-running servers expose allocator pressure that single-shot benchmarks never see — fragmentation, jemalloc bin contention, slow drift in resident-set size. v3.6.0 of HeliosDB Lite (and v7.4.0 of Full) introduced per-request arena allocation as a first-class executor feature. This post explains what changed for operators.

## The shape of the win

SQL engines do a lot of short-lived allocation: tokenise a query, build an AST, plan it, materialise intermediate buffers, drop everything when the response is sent. Without per-request scoping, every one of those allocations rides the global allocator. That's fine for a few requests per second; it's a different story at thousand-RPS sustained on a multi-tenant server.

Per-request arena allocation gives the executor a scratchpad that lives only for the duration of a single statement. Allocations bump a pointer; deallocation is dropping the arena. There is no cross-request fragmentation because there is no cross-request data.

## What you'll see in production

- **Lower allocator pressure on multi-threaded workloads.** jemalloc bin contention drops because most per-request work is bumps, not `malloc` calls.
- **Predictable memory ceilings.** A query's worst-case scratch usage is easy to bound from the per-query metrics; you can plan capacity off observed maxima.
- **No memory-safety footguns.** The arena owns everything; lifetimes are tied to the request scope. No double-free, no use-after-free.
- **Easier perf bisection.** A regression in per-query scratch bytes points directly at the operator that grew — the executor exposes the number on the wire.

## What you won't see

Latency on a single point query is unchanged within noise. The wins compound under sustained pressure — that's where allocator behaviour matters most. Synthetic single-shot benchmarks don't show the difference; soak tests at sustained RPS do.

## How to inspect it

Per-query arena bytes are exposed in `helios_query_stats`. A regression watch is one query:

```
SELECT query_fingerprint, p99_arena_bytes, executions
FROM helios_query_stats
WHERE last_seen >= now() - interval '1 hour'
ORDER BY p99_arena_bytes DESC
LIMIT 20;
```

If a query's `p99_arena_bytes` jumps after a deploy, the planner is the prime suspect. The executor team treats arena bytes as a first-class regression signal alongside latency and tuple count.

## Where this came from

The pattern isn't new — PostgreSQL has memory contexts, DuckDB has its own arena, the JVM has TLABs. We borrowed the shape and fitted it to a per-request lifetime. The benefit isn't the technique; it's that the engine takes responsibility for it instead of letting the global allocator absorb the cost.

HeliosDB Lite is source-available under SSPL-1.0. Repository: [github.com/dimensigon/HDB-HeliosDB-Lite](https://github.com/dimensigon/HDB-HeliosDB-Lite).
