How Huge Pages Improve PostgreSQL, Oracle, and Redis Performance

When a database grows and memory is used inefficiently, queries start to lag precisely during peak hours. We configure Linux Huge Pages turnkey: select the reservation mode, verify the result under your workload, and hand your team a clear maintenance procedure. Response latency decreases without rewriting the application.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Why the database hits a memory ceiling: the role of Huge Pages Linux

As long as the database working set fits in memory and CPU cache, the difference between a regular page and a huge page is invisible.

Once the data volume outgrows the cache, each page table miss turns into a walk through several levels — and this is no longer a few cycles per request, but thousands for every full index pass.

Requests begin to queue not because of a resource shortage, but because of how that resource is sliced.

By default, the kernel divides memory into 4 KB pages.

For the general case this is convenient, but for a database server it means something different: the page table grows along with the buffer pool, its entries constantly miss the address translation cache, and memory management overhead eats CPU time that should go to the data itself.

Add kernel memory fragmentation to this. Over months of operation, free areas spread out, assembling a contiguous region for a large buffer becomes harder, and the kernel spends cycles on compaction instead of serving requests. Restarting the service helps temporarily — the memory partitioning scheme itself does not change.

On graphs, this looks like a growing share of system time and page queues.

Query latency growth starts long before memory runs out: the customer sees not a failure, but “it got slower at peak.” This is an inconvenient class of degradation — it is usually attributed to load and tolerated for months.

Huge Pages Linux change the scale of the task: one page covers an area that previously required hundreds of entries, the page table shrinks, misses occur less often, and the kernel stops being torn between serving requests and managing memory. Next we break down how this works and in which scenarios it gives a measurable effect.

What switching to huge pages delivers: measurable effect

Huge pages remove work that should not exist in the database. When PostgreSQL, Oracle, or Redis keep their working set in shared memory, the kernel hands it out in small pages — and almost every access forces the CPU to look up an entry in the page table.

On the hot path, this is a noticeable share of cycles going not to queries but to address recalculation.

Switching to huge pages changes the scale: one entry in the translation buffer covers hundreds of times more memory, and misses on it drop by an order of magnitude.

This is visible in three values — kernel CPU load under the same request is lower, database response time stops fluctuating at peak, throughput grows without adding hardware.

The effect is strongest where there is a lot of in-memory data and accesses are random: analytics, indexes, session cache.

The second result is an eliminated class of memory failures. A contiguous segment for the shared buffer is allocated at startup, and if memory is fragmented by then, the service either fails to come up or crashes later as load grows.

Pre-reserved huge pages are allocated deterministically, so the cost of downtime stops depending on how long the host has been running.

The effect is verifiable, not taken on faith: we capture a profile before and after — response time under peak, core utilization, number of translation misses, and database behavior on restart.

Huge Pages Linux modes: explicit reservation and transparent mode

In Linux, two independent mechanisms are responsible for huge page support: explicit reservation and transparent merging. They allocate memory differently and behave differently when it is scarce — so the choice of mode directly affects DBMS stability under load.

Explicit reservation (hugetlbfs) pins a page pool in advance, via kernel parameters, and holds it for the entire runtime. DBMS instances see ready-made pages, pool size is predictable and does not depend on current memory state.

The trade-off is that the pool must be calculated for peak, and its exhaustion means allocation failure rather than silent degradation.

Option When it fits Limitations
Explicit reservation DBMS and services with long-lived shared memory: PostgreSQL, Oracle, Redis Pool is fixed in advance; recalculating requires restarting the service
Transparent merging General workload, computations, short-lived processes No allocation guarantee: background defragmentation may not keep up, memory reclaim is delayed
Hybrid: transparent enabled, explicit — selectively Mixed nodes where the database is not the only consumer Need to monitor that the background does not evict the reserved memory

Transparent merging does not require manual configuration: the kernel itself assembles huge pages from small ones. But allocation happens on a best-effort basis, not on demand — for a long-lived database process this means an unpredictable working set size.

Therefore explicit reservation is chosen for a DBMS: only it provides deterministic size and smooth latency. Transparent mode is left for other processes or disabled on nodes where the database is the main memory consumer.

How we implement huge pages: stages of engineering work

We structure the order of work so that memory is not taken away from a running service and rollback is possible at every step.

First, configuration audit: capture Hugepagesize and HugePages_Total/Free counters from /proc/meminfo, look at transparent pages mode, process limits, distribution across memory nodes, and the actual size of database or cache working sets.

  1. Configuration audit. Record current consumption, the address translation buffer miss rate, and free memory headroom — without this, page calculation will be guesswork.
  2. Reserve calculation. Calculate the number of pages for the peak working set with headroom for growth and separately for service processes, so that after enabling the reserve the system does not go into swap.
  3. Kernel configuration. Set the page reserve, disable transparent pages or move them to managed mode, pin the parameters in the bootloader and system units so they survive a reboot.
  4. Trial enablement. Bring it up on one node or replica, verify that the service picked up the pages and that memory fragmentation does not prevent allocating them after long uptime.
  5. Load testing. Compare with the baseline measurement: response time under peak, cache behavior, latency stability, absence of restarts, and consumption growth during long operation.
  6. Observability. Set up collection of page counters and alerts for shortage — otherwise the problem will manifest as a sudden failure at the next service start.
  7. Handover of maintenance. Hand over to your team the configurations, placement scheme, planned restart instructions, and diagnostics checklist.

We agree on the parameters at each step with your engineers: changes to the memory reserve affect all services on the node, so we implement them in stages while preserving the ability to return to the previous configuration.

What your team keeps after implementation

We do not leave the configuration as verbal agreements: every Huge Pages parameter is documented together with the reason it was chosen.

Below is a set of artifacts your engineers can use to maintain the configuration themselves and reproduce it on new Linux nodes without our involvement.

  • Documentation package — kernel and DBMS parameter values with rationale: why this reserve size was chosen and what will change if it is reduced.
  • Memory placement scheme — node map: how many pages are pinned to each instance, where headroom is left, how memory is divided when neighboring services restart.
  • Maintenance procedures — procedure for checking the reserve after a kernel update and reboot, scheduled control of fragmentation and pinned page leaks.
  • Access policies — who is allowed to change parameters, through which configuration management system, which edits require approval, and how auditing is performed.
  • Rollback instructions — step-by-step return to regular pages: which services are stopped, in what order, how to verify that metrics have returned to baseline.
  • New node checklist — what is run before commissioning: reserve allocated, DBMS sees it, metrics normal.

The artifacts are formatted the way they are actually used: ready commands, configuration templates, change history. You handle maintenance yourselves — we only get involved in new tasks.

Case study: how we reduced query latency on a loaded database

The production environment is a service with a PostgreSQL database, where steady load once a day turns into a short but severe peak.

Before the work, tail query latencies at this peak exceeded the target threshold, and process resident memory grew in steps and did not return to baseline after traffic subsided.

Measurements were taken in production without stopping the service: latency distribution by percentiles, memory consumption, address translation miss frequency, and the size of service structures for shared pages.

We separately captured the profile specifically under peak load — that is where degradation was most noticeable, while during quiet hours it was almost invisible.

Shared structures were moved to huge pages and a pool was reserved at process startup so it would not fragment during operation.

We added a check of the available pool to the startup procedure, and an alert for its exhaustion to monitoring: without this, the gain disappears after the very first node reboot.

Tail latencies at peak were reduced by about three times, and the share of queries exceeding the target threshold fell from 4% to 0.3%. The process stopped exceeding the pre-reserved amount, and the peak passes without stepwise memory growth and without unplanned restarts.

Measurements were repeated under the same load and with the same query profile, so the numbers are comparable, not pulled from a convenient window.

Rollback here is a configuration edit and restart, so such a run can first be performed on a copy of your environment and compared with current measurements.

What to do if huge pages are already partially configured?

A partially configured environment is when large pages are already allocated but not coordinated with each other: some parameters are set manually in a running system and last until the next boot, some are described in the bootloader profile, and the pool size is set in the DBMS settings.

Checking the current state starts with /proc/meminfo: we compare total, reserved, and free page amounts — the gap between them immediately shows which allocation is idle and never reaches the process.

The second typical source is parameter conflict.

A DBMS switches to huge pages only if the amount for its buffers is fully covered by allocated pages and the limit on locked process memory is removed; if there is an incomplete match, the service either silently starts on base pages or does not start at all.

A separate trap is kernel transparent huge pages: under load they rearrange the layout, and manual allocation becomes pointless, so they are explicitly disabled.

Then we clean things up: leave a single source of truth for boot parameters and system limits, remove manual tweaks from autostart, and align the allocation size with the pool size with headroom for replicas and service processes.

We build a no-downtime transition sequentially: first configure and test on a replica, switch the primary node role, then repeat the same on the former primary. The reboot step remains, but application availability is not interrupted.

After switching, we return to verification: we look at the share of actually used huge pages and allocation failures in the kernel log. If the failure counter grows, the amount or limits were chosen incorrectly, and the fix must be repeated until a stable result.

Technical concerns: answering common questions

Implementing Huge Pages changes how memory is allocated at the kernel level: the database receives large pages instead of a set of small ones.

Therefore technical concerns arise before problems do — an engineer wants to understand where the risk boundary is: what will happen to replicas and the cluster, and how quickly to roll back if the load profile turns out different.

The change is local to the node: transmission of changes between the primary node and replica goes through a separate stream and does not depend on page size. Below are the things that most often come up during approval.

Will the behavior of the primary node and replicas diverge?

No, if page size is set the same on all nodes. Process shared memory requires special attention: it is allocated as a single block, and with different page sizes the shared segment on the replica will not come up.

Therefore the configuration is rolled out to the cluster in one window, not node by node — then the impact on replication is zero.

What does rollback look like if something goes wrong?

Rollback is two-level. The kernel parameter returns to its previous value and is applied after a node reboot; the database settings return to the baseline captured before implementation.

We keep both configurations working and tested, so rollback does not require rebuilding: it is a controlled operation in a known window.

What implementation risks should be planned for in advance?

The main one is a shortage of contiguous physical memory: if reservation is not done at startup, some pages cannot be allocated and the node returns to normal mode. The second is an error in reserve calculation when it evicts other processes.

Both are eliminated by measuring on a copy of the production node under real load: we look at query latency, share of time in system calls, and buffer stability. Rollout to production happens only after that and with a rollback plan in hand.

Let's discuss the task: what we will clarify and how we will start

The start is one business conversation: you describe the environment and the task, and we come back with a work plan and estimate. To avoid clarifying inputs along the way, we capture them immediately — this determines which memory settings are even worth touching.

  • load profile: what predominates — short transactions, analytical queries, or cache accesses, and at which peaks degradation is noticeable;
  • host memory state: whether transparent huge pages mode is enabled, which kernel parameters are set, how resources are distributed between roles;
  • environment layout: where PostgreSQL, Oracle, and Redis are located, whether there are replicas and read/write separation;
  • maintenance windows: when a database service restart is acceptable and for how long a node can be taken out of operation;
  • rollback requirements: how quickly previous parameters must be restored if metrics decline;
  • access: a staging environment close to production and monitoring data that shows actual memory distribution;
  • success criterion: what we consider the result — reduced query latency, increased cache hits, or stability under peak.

In response you receive a work plan: where we start, what we test on staging, by which metrics we accept the result, and at which values we roll back changes. The start procedure is simple — we agree on the environment inputs, fix the window, and come with an estimate. Describe the task, and we will come back with a concrete plan.