Back to the blog ·

One server, seven services, 7.7 GB of RAM

On a single machine with 7.7 GB of memory I run: Nextcloud, GitLab, n8n, YouTrack, a vector database, a Minecraft server, and the nginx that distributes all of it. This is not a recommendation. It is a field report on what runs out first in a setup like this – and it is not what you would expect.

The numbers

The current distribution:

GitLab      3535 MB
YouTrack    1680 MB
n8n          668 MB
MariaDB       97 MB
PHP-FPM       79 MB

In total 6.0 of 7.7 GB are in use, 1.2 GB genuinely available, and 1.6 GB sit in swap.

Two services account for 5.2 GB between them – more than two thirds. And they are precisely the two you are most likely to take for granted on a machine like this.

GitLab is not a service, GitLab is a platform

3.5 GB for version control is not a broken installation, it is the design. Underneath sit a Ruby web server with several worker processes, a background job runner, a PostgreSQL, a Redis, a dedicated Git service, and a process supervisor holding it together. It is a complete development platform with issue tracking, registry and CI – and you pay for that in memory, even if all you want is somewhere to put repositories.

Anyone who genuinely only needs Git gets away with a fraction using Forgejo or Gitea. That is the change I would most likely make – and the only reason it has not happened is CI pipelines I do not want to touch.

YouTrack, in turn, is a Java application, and 1.7 GB is unremarkable for a JVM on default settings. There is room to tune the heap there, with the usual price: less memory means more work for garbage collection.

Swap helps – but not with what people think

I raised swap to 5.9 GB, and that was the right call. But not for the reason usually given.

Swap does not make an undersized server fast. What is swapped out is slow, and no amount of it changes that. What swap prevents is something else, and far more important: the kernel killing a process during a memory spike. Without a buffer, such a spike takes out some service – often not the guilty one, but the largest. Suddenly your issue tracker is down because an import wanted too much memory.

With enough swap, those moments become sluggish instead of fatal. Sluggish you can observe and fix; dead you notice when somebody asks.

Bare metal instead of containers – a deliberate choice

Almost everything here runs directly on the system rather than in containers. The reason is simply memory: every container brings its own libraries, and on a tight budget that adds up.

The price is dependencies getting in each other's way. This machine runs two PHP versions side by side because two applications have different requirements. It works, but it is exactly the kind of detail you have forgotten six months later and rediscover during an update.

If you have the memory, use containers. If you do not, write things down.

The honest balance

This setup carries my own usage without trouble. It would not carry customer load, and it has no redundancy – if the machine dies, everything is gone until I rebuild it.

What I take from it, and what holds for larger environments too: the bottleneck is rarely where you assume. I would have bet on the databases, the Minecraft server, the vector database. Together they use less than a quarter of what version control helps itself to.

So: measure first, optimise second. ps -eo rss,comm --sort=-rss | head takes a second and ends every discussion that would otherwise run on assumptions.