Build2 distinct publishers3 min readPublished
The compute node owns no durable state, so it can resize in place, and Neon puts the average production database at 32,016 size changes a month, a figure that describes its fleet's variance more than it predicts yours.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The part worth studying is the retreat from cgroups. An earlier version of this autoscaler hung memory decisions off the cgroup `memory.high` event, and crossing that threshold makes Linux reclaim memory and throttle every process inside the cgroup [11]. That design measured memory pressure by waiting to be punished for it. Polling replaced it because polling proved more predictable and stable, and it still yields a 100-millisecond view of what Postgres is using [11]. That inner loop runs fifty times more often than the autoscaler-agent's read of overall VM memory metrics [3], which is the correct asymmetry: brief CPU over-commit makes queries slower, while allocating past the VM's RAM lets the kernel terminate processes [12].
The working-set signal is the one I would take to my own design. When a page is not local, the compute fetches it from the pageserver and caches the result in the Local File Cache, a disk-backed cache sized to fit in the kernel page cache and acting as a resizable extension of shared buffers [13]. Misses therefore park queries on network waits, which lowers CPU utilisation exactly when a bigger cache would help, and for many OLTP workloads performance changes sharply once the working set fits locally [14]. A utilisation-only autoscaler reads that as an idle machine and shrinks it. Counting every accessed page exactly would need too much memory, so the size is estimated [15]; the text supplied to me stops before naming the estimator.
Now the headline number. Neon reports 32,016 compute size changes per month for the average production database, or roughly one every 81 seconds [3]. The arithmetic checks: a 30-day month is 2,592,000 seconds, and dividing by 32,016 gives 81 [1]. It also works out to about 1,067 changes a day, near 44 in an hour [2], which is the density you would expect in the one-hour sample chart the Databricks copy uses instead [16]. For that rate to describe your database, two things have to hold. Your load has to actually move on a minute scale, and your configured minimum and maximum have to be far enough apart that the algorithm has somewhere to go. A steady service at constant QPS would resize rarely, and the win would appear on the invoice rather than on the chart.
Which brings back the decision the pitch says is gone. It is not gone, it is re-expressed: the target is the largest of `cpuGoalCU`, `memGoalCU` and `lfcGoalCU`, clamped to the minimum and maximum compute sizes the user configured [7]. So you still size, once, as a range. The difference that matters is what being wrong costs. Set the maximum too low and you get slower queries under the 90% CPU goal and the 75% memory goal [8][9], which leave 10% and 25% headroom respectively [4]. Set it too high and the most pessimistic of three signals decides your bill. That is a better failure surface than a fixed instance class, and it is available only if the box holding Postgres holds none of the data [5].
Ranked by verification strength, evidence, and original report placement.
Databricks writes that choosing a database instance size before you know the workload is an old building pattern, that the process is generally wonky and feels very wasteful of compute, especially now that compute is becoming a luxury.
Lakebase Postgres omits the sizing experience altogether thanks to autoscaling; the responsiveness comes from in-place VM resizing and an algorithm that tracks CPU, memory, and the database's working set.
Traditional Postgres runs as a stateful process tied to a machine and its disks, so replacing or resizing that machine is a database operation because the machine owns both execution and durable state.
In Lakebase Postgres the compute layer runs Postgres and executes queries, using RAM and local NVMe for low-latency access and owning no durable state, while the storage layer owns durability and history: WAL replicated by safekeepers on SSDs, pageservers on SSDs reconstructing page versions, and object storage keeping the long-term immutable record.
A compute node can therefore start, stop, move, or change size without moving the database underneath it, which the post calls an essential foundation.
The autoscaling algorithm tracks three signals, each producing its own target compute size (cpuGoalCU for CPU load, memGoalCU for memory use, lfcGoalCU for compute-cache working set size), and the final scaling target is the largest of the three, constrained to the minimum and maximum compute sizes the user configured for that database.
Distinct publishers with included, body-backed reporting in this cluster.
1 article · August 31, 2026
1 article · August 31, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
invest
Agents push one CRM account from 5GB to 40GB in thirty days1 distinct publisher
build
Notion's agent stack is live, not slideware, and it only changes one of your decisions1 distinct publisher
security
ShinyHunters dumps 12.9 million Carhartt records after a refused $3.3 million ransom1 distinct publisher
build
The 680 MB database that was really a 17 GB disk: self-hosted support platforms fail at month six1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Rich mechanics, zero outside verification
The mechanism is described at a level most vendors skip — named goal variables, exact sampling intervals, exact thresholds, a component that vetoes unsafe downscales, and a candid note about the cgroup design that was abandoned. That specificity is worth something. But every word of it comes from the company that ships the product, in one text published twice, and not a single performance number, latency figure or reproducible test accompanies the claim that the loop works.
One self-reported average and an unlabelled hour
Usage evidence amounts to two vendor-supplied artifacts: a monthly resize average with no denominator, and a chart of an unnamed sample covering sixty minutes. Nobody names a customer, a workload, or a database count. That the resize rate implies a live production fleet is real signal — it is just the only signal, and it arrives without a definition.
Sizing didn't vanish, it moved
The promise is that sizing goes away; the mechanism says the final target is clamped to the minimum and maximum you configured. You still pick two numbers, and no one here helps you pick them. Add a headline statistic that measures how much Neon's own fleet fluctuates rather than what any workload should expect, and the framing runs modestly ahead of what is shown — though the engineering detail is honest enough to keep the gap small.
Vendor telling its own story twice
Both publishers are the same commercial interest — Neon under Databricks — and the two posts are one text. The product is what is being sold, the metrics are self-measured, and the editing between versions runs in the direction of brand consolidation: Databricks removes the Neon name and the number, Neon keeps both for its developer readership. There is no disinterested party anywhere in the story.
Coherent, consistent, single-origin
Internally the account holds together: the thresholds, the polling frequencies and the reason memory needs a faster signal than CPU all reinforce one another, and the two publications do not contradict each other on any mechanism. Confidence stops where corroboration does — the duplication across two sites adds brand reach, not a second observer, so the quantitative claims stand exactly as far as the vendor's word carries them.