Blog · Plugins & code

Why your lifesteal plugin eats 4 GB (and the fix)

The short header

Four gigabytes for hearts and kills is not plugins being heavy — it is an N+1 on every kill, a cache nobody evicts, and writes on the wrong thread. The shape of the fix.

Where the memory actually goes

Run spark --heap on a server like this and the picture is always the same: one Map<UUID, Profile> loaded at join, holding every heart transaction the server ever saw, never evicted — plus a second copy keyed by name for tab lookups. Sixty concurrent players, four gigabytes, and an owner convinced "plugins just need RAM".

They don't. They need an eviction policy.

The N+1 on every kill

The kill path is where lifesteal plugins go to die. Per heart, per kill: a SELECT for the victim, an UPDATE for the winner, an INSERT for the log — sometimes three of them on the main thread, synchronously, while forty players fight in an event. Ten players trading hearts in one fight is a hundred round-trips the tick never sees.

The fix, in order

  1. Repository layer. One interface — load, save, query. Every SQL lives behind it, and swapping databases stops being a rewrite.
  2. Evict on quit. Save flush, drop the entry. Nothing personal lives in memory after the player leaves.
  3. Cap the cache. LRU at a few hundred entries beats a map that grows until the GC gives up. The hot players stay warm; everyone else costs nothing.
  4. Write behind, in order. One executor, a bounded queue, batched transactions. Kills in a fight collapse into one write, off the tick thread.
  5. Log tables get seasons. Partition or prune at reset — the log is history, not state.

Same plugin, same sixty players, same fights: about 380 MB steady after the rewrite. The four gigabytes were never the price of the genre.

Sources

spark — memory and heap profiling — read on September 2026

About RnK

RnK is a Minecraft developer with six years in the game — plugins, server setups and performance work across Paper, Spigot and Folia backends. Three networks run day to day; the rest of the time is client work. The bench is open on Discord.

Read next

Config files players can't break