Hosting account resource limits: CPU, RAM and I/O done right

What hosting account resource limits for CPU, RAM, I/O, processes and inodes do, how Linux enforces them, and how to size plans so one site can't sink a server.

Diagram: each hosting account inside its own CPU, RAM and I/O limits

Key takeaways

  • Hosting account resource limits keep a busy or hacked site's problems inside its own account.
  • On modern Linux, CPU, memory, processes and disk speed are enforced with cgroups, and disk space and inodes with filesystem quotas.
  • A memory limit is a ceiling, not a reservation, so plans can add up to more RAM than the server has.
  • Check that the PHP workers your plans allow fit in RAM, then tune plans from real usage history.

Hosting account resource limits are the caps on CPU, memory, processes, disk throughput, disk space and file count that each hosting account may use. On Linux, CPU, memory, processes and I/O are enforced by the kernel through cgroups, and disk space and inodes through filesystem quotas. The point is not to squeeze customers. It is to make sure that a bot flood, a broken plugin or a crypto miner slows down one account instead of the whole server.

This article covers each type of limit, how Linux enforces it, how to size plans so they don't promise more than the hardware can deliver, and how to set it all up, both in ZoPanel and by hand.

Why does a shared server need per-account limits?

On a shared server every site uses the same CPU, the same RAM and the same disk. Without limits, one account having a bad day means a hundred other sites have a bad day too. The usual culprits:

  • Bots and crawlers hammering uncacheable URLs (search, product filters), each one a full PHP run plus database queries.
  • Broken plugins stuck in a loop or running heavy queries on every page.
  • Compromised sites mining crypto, sending spam or forking hundreds of processes.
  • A genuinely busy customer, say a shop running an ad campaign. Good news, but that customer should be on a bigger plan.

Limits turn all of these into one account's problem. They are also what makes tiered plans meaningful: a bigger plan gets more CPU, RAM and PHP workers.

What kinds of hosting resource limits are there?

Limit What it measures What happens when it's hit
CPU Percent of one core (100% = one core, 200% = two) Processes are throttled; the site slows down but keeps working
Memory All processes in the account, added up The kernel stops a process inside that account, usually a PHP worker
Processes Processes and threads New processes can't start, so new requests may fail
Disk throughput (I/O) MB/s read and written Disk operations are slowed
Disk space MB Writes fail, for that account only
Files (inodes) Number of files and folders No new files can be created
Database connections Concurrent connections per database user New connections are refused
Emails per hour Outgoing recipients Messages over the limit are refused
PHP workers PHP requests running at once Extra requests wait in a queue

CPU and memory are the two that get misunderstood. CPU is elastic: going over just makes things slower. Memory is not: when an account hits its ceiling, the kernel has to stop one of its processes. So memory set too low shows up as intermittent 502 or 503 errors, while CPU set too low shows up as a slow site.

How does Linux enforce the limits?

cgroups and systemd

Ubuntu since 21.10 and Debian since 11 use cgroups v2 by default. systemd manages cgroups through "slices": put every process of an account into one slice and attach limits to the slice. The main properties, per the systemd.resource-control documentation:

  • CPUQuota= is a percentage of one CPU and can go above 100% to allow several cores.
  • MemoryHigh= throttles and reclaims memory above the value; MemoryMax= is the hard ceiling, past which the kernel kills processes.
  • TasksMax= caps processes and threads.
  • IOReadBandwidthMax= and IOWriteBandwidthMax= cap throughput on a block device.

You can try it on a logged-in user's slice:

# Limit the user with UID 1001 to one CPU core, 1 GB of RAM and 200 processes
sudo systemctl set-property user-1001.slice CPUQuota=100% MemoryMax=1G TasksMax=200

# See which slices use the most resources
sudo systemd-cgtop

The catch with doing it by hand: out of the box, PHP-FPM runs every pool under one master process in php8.3-fpm.service. All customers' PHP then lives in the same cgroup, so a per-user slice limit never touches PHP, which is the thing that uses the most resources. Real per-account limits need a separate PHP-FPM master per account running in that account's slice, along with its cron jobs and SSH sessions. That is plumbing a control panel should do for you.

Disk quotas

Disk space and inodes are limited with filesystem quotas. The filesystem holding /home must be mounted with usrquota (ext4) or uquota (XFS), then quotas are switched on and set per user. A quick check:

sudo repquota -a        # space and inodes used by every user

Without quotas, disk usage is only measured, never stopped, and one account can fill the disk and take everyone's databases and mail down with it. Inodes matter too: file-based caches and uncleaned session folders can create millions of tiny files, slowing backups and exhausting the filesystem's inodes while the disk still looks half empty.

Databases and email

MariaDB limits connections per user:

ALTER USER 'alice_shop'@'localhost' WITH MAX_USER_CONNECTIONS 30;

The hourly email limit lives in the mail server, and it matters more than it looks: one hacked site sending spam can get the server's IP onto a blocklist, at which point every customer's mail lands in spam.

What about CloudLinux?

On cPanel, DirectAdmin and Plesk servers the common answer is CloudLinux OS, a commercial distribution. Its LVE technology limits CPU (SPEED), physical memory (PMEM), I/O, IOPS, processes (NPROC) and entry processes (EP, concurrent requests into the account), as described in CloudLinux's documentation. Visitors see a 508 error when EP is reached. The idea is similar to cgroups, but it needs a CloudLinux licence on top of the panel licence. Check CloudLinux's site for current pricing.

How do you size the limits?

There is no universal number, but there is arithmetic that stops you from shooting yourself in the foot.

Start from PHP memory

A busy WordPress PHP worker typically holds tens of megabytes, more with heavy plugins. A plan's memory limit has to fit the PHP workers it allows:

plan memory ≥ PHP workers × memory per worker + room for cron, apps and SSH

A plan with 10 PHP workers at about 60 MB each needs at least 600 MB for PHP, so 1 GB is sensible. Give a plan 20 workers and 512 MB, and the kernel will be killing workers every time the site gets busy.

Overselling, properly understood

A memory limit is a ceiling, not a reservation. An 8 GB server can host 50 accounts with a 1 GB ceiling each, because most sites are idle most of the time. That is controlled overselling, and it is how shared hosting has always worked. The risk is many accounts hitting their ceilings at once, so you also need protection at server level: a reserve of memory for MariaDB, mail, the web server and the panel, so you can still SSH in however hard customers push.

Be more careful with disk space. A full disk breaks databases and backups.

Suggested starting points

This table is a starting point to adjust against real customers, not a measurement:

Plan CPU Memory PHP workers Processes
Brochure site 50–100% 512 MB–1 GB 5–10 100
Business site, busy blog 100–200% 1–2 GB 10–20 200
WooCommerce store 200% and up 2 GB and up 20 and up 300

After a couple of weeks, look at real usage history. Accounts that keep hitting the ceiling are upgrade candidates; accounts that never pass 10% tell you the server has room.

Common mistakes

  1. Quotas not enforced. A disk limit in the UI does nothing if the kernel isn't enforcing it.
  2. Plan memory too small for its PHP workers. Intermittent errors that customers blame on their code.
  3. PHP memory_limit above the whole plan's memory. A heavy script is killed by the kernel instead of getting a clear PHP error.
  4. No email limit. One hacked site is enough to get the server's IP blocklisted.

Setting hosting account resource limits in ZoPanel

ZoPanel puts every limit in a package. Go to Packages and click New package, or edit an existing one. Each field is described in the Packages and limits documentation. The essentials:

  • CPU, RAM, processes and disk speed are systemd cgroup limits on everything the account runs: PHP, apps, cron jobs and shells. Each account has its own slice and its own PHP-FPM pool, so the limits really do apply to PHP. A process over the RAM limit is stopped by the kernel inside that account only.
  • Disk and files (inodes) are kernel quotas. Check that quotas are enforced in Settings → System → Disk quotas.
  • Disk speed left empty is set automatically at about 40 MB/s per GB of package RAM, between 30 and 300 MB/s.
  • Database connections left empty become 3 × PHP workers, at least 30.
  • Emails per hour counts recipients sent through PHP mail() and SMTP logins; anything over the limit is refused.
  • PHP always running is for premium plans: PHP never sleeps when idle, at a cost of about 20–60 MB of RAM per site.

The installer's Business package is a reasonable starting point: 5 websites, 10 databases, 100% CPU, 1 GB RAM, 200 processes, PHP memory_limit 256 MB and 10 PHP workers. Editing a package applies the new limits at once to every account on it.

On top of per-account limits, ZoPanel splits the server's RAM into a system reserve (MariaDB, mail, nginx, the panel) and a limit for all customers together, as explained in Performance and capacity. When many sites surge at once, customer processes are throttled first, while SSH, the panel and the databases keep their memory.

To tune packages from real data:

  • The Tuning page warns when the PHP workers allowed by all packages together do not fit in RAM.
  • Usage history records each account's CPU and memory every 5 minutes, over 24 hours, 7 days, 30 days or 1 year. Administrators open it from an account's menu under Accounts; customers see it on their Resources page (see Operations and monitoring).
  • Resellers (a Pro feature) build packages for their own customers but can never exceed their own package.

Account limits are one layer of a broader isolation model; why a hosting panel should never run as root covers the others. If you are planning density, how many WordPress sites a 4 GB VPS can host has measured numbers.

The takeaway

Resource limits don't make sites faster. They decide whether a small incident stays small. Give each plan enough memory for its PHP workers, enforce disk quotas, cap outgoing email, keep a reserve for the system, and tune plans from usage history rather than guesswork.

You can try the full package and limits system on ZoPanel's Free plan (3 hosting accounts, 10 websites, 10 databases, no time limit) by installing with curl -fsSL https://get.zopanel.net | sudo bash. When you need more sites, see pricing.

Frequently asked questions

Is a 503 error caused by resource limits?

It can be. When an account hits its memory ceiling, the kernel stops a PHP worker and the request it was serving fails; when every PHP worker is busy, new requests queue. Check the account's CPU and memory history at the time of the error before blaming the code.

Should CPU or memory be limited more tightly?

Memory needs more care, because going over it kills a process while going over CPU only slows things down. Give each plan enough memory for its PHP workers, and be more generous with CPU, since most sites don't use it continuously.

Can the plans' memory limits add up to more than the server's RAM?

Yes, and that is how shared hosting works, because a limit is a ceiling rather than a reservation. The condition is that the server keeps a memory reserve for system services and has a way to cope when many accounts hit their ceilings at once.

Do I need CloudLinux to limit resources?

No. A modern Linux kernel has cgroups v2 and filesystem quotas, which cover CPU, memory, processes, I/O, disk space and inodes. CloudLinux is a commercial product that adds management tools around this kind of mechanism; some panels, ZoPanel among them, use cgroups directly through systemd.

What is an inode limit and why does it matter?

An inode limit caps how many files and folders an account can create. File caches, session folders and unpruned libraries can produce millions of tiny files that slow backups and can exhaust the filesystem's inodes while disk space remains. The limit keeps that problem inside one account.