Guides

Dedicated CPU cores & reservations

Pin a project to specific CPU cores, reserve them so nothing else on the server uses them, and set CPU priority and a memory guarantee.

Resources decide how MUCH CPU and memory a project may use. CPU placement decides WHERE it runs and how it is treated when the server is busy. It is for the cases where a limit is not enough: a latency-sensitive API that must not share cores with a batch job, a database that should keep its memory when the box fills up, or a noisy neighbour you want to push to the back of the queue.

Everything on this page is optional and off by default. A project with no placement runs exactly as before.

What you need first

  • A project deployed to one of your own servers (placement uses Docker on that server; cloud and cluster projects are sized differently).
  • Permission to change the project's settings.

The four settings

SettingWhat it doesDocker flag
Dedicated coresRuns the project's containers only on the cores you pick.--cpuset-cpus
Reserve exclusivelyAlso moves every other Synq container on that server off those cores.--cpuset-cpus on the others
CPU priorityRelative weight under contention: Low 512, Normal 1024, High 2048, or any value from 2 to 262144. It never limits an idle server.--cpu-shares
Memory reservationA soft guarantee. When the server runs short of memory, containers above their reservation are reclaimed first.--memory-reservation

Pin a project to cores

Open the project's Resources section

Open the project and choose Resources in the project menu. Below Machine Power is the CPU & memory placement card. Open it; Synq reads the server's core count from its Docker daemon (for example "prod-1 has 8 cores.") and, when it can, the topology from lscpu, so cores are grouped by socket and hyper-thread siblings show their physical core.

Pick the cores

Under Dedicated cores, click cores to select them; Clear selection starts over. The legend shows Selected, Reserved by another project (disabled), Used by another project (you can still share them) and Free. Hover a core to see who holds it.

Optionally reserve them exclusively

Turn on Reserve exclusively to keep every other Synq-managed container (other projects and their services) on the remaining cores. At least one core always stays unreserved, for Synq itself and your other apps.

Set priority and memory, if you want

CPU priority offers Low, Normal, High or Custom (a weight from 2 to 262144; normal is 1024). Memory reservation takes a number of MB; it can't be more than the memory limit set under Machine Power.

Save placement

Press Save placement. The change applies live: Synq runs docker update on every affected container, so nothing restarts. The toast says Placement applied to N running containers. and names any that could not be updated. In effect now shows the cores, CPU weight and memory reservation actually in force. Remove placement clears everything.

For a compose or monorepo project, the Apply to menu picks Whole project or a single service, and the Per service list shows which services have their own placement (Same as project otherwise; press Edit to change one). A service without its own placement uses the project's, field by field, so a service that only sets a CPU priority still runs on the project's cores.

If the server can't be reached, a placement that only sets CPU priority or Memory reservation is saved anyway and applied when containers are next created. Picking cores (with or without Reserve exclusively) needs the server to be reachable, because Synq reads its core count first; otherwise the save is refused with The server's CPU count could not be read, so cores cannot be pinned right now.

How exclusivity is enforced

A reservation is enforced in two places, which always compute the same answer:

  1. Live, when you save. Every Synq container on the server is updated to its effective cores: the reserving project gets its cores, everyone else gets all the others. Releasing a reservation gives every container every core again.
  2. At every container create. A deploy, a rollback, a zero-downtime swap, a restart that recreates a container and a scale-out all read the current reservations and create the container on the right cores. Placement is read live, never from an old deployment snapshot, so rolling back to a release from before another project reserved cores still stays off them.

The server page shows the same picture: Servers → the server → Overview → CPU cores lists which project pins or reserves which core and each container's current cpuset, with a Re-apply button that runs the live update again.

Rules Synq checks before saving

  • The cores must exist on the server.
  • Two projects (or services) cannot reserve overlapping cores exclusively.
  • A reservation cannot take cores another project is pinned to; unpin it there first.
  • At least one core must stay unreserved.
  • A memory reservation cannot exceed the project's memory limit.

What a reservation does not isolate

Host processes and the control plane

Synq's own containers (API, dashboard, edge, database and cache) are never restricted, so a reservation can never starve the platform. Processes that run directly on the host, outside Docker (sshd, cron jobs, the Docker daemon itself), can still be scheduled on reserved cores.

For hard isolation, keep the kernel scheduler off those cores as well: add isolcpus=2-3 (your reserved cores) to the kernel command line, for example in GRUB_CMDLINE_LINUX in /etc/default/grub, run update-grub and reboot. Docker can still place pinned containers on isolated cores, and nothing else will run there.

Build containers are short-lived and are not moved; they may briefly use reserved cores while a build runs.

From the API

# Read the placement, the server's cores and who holds them
curl -H "Authorization: Bearer $SYNQ_TOKEN" \
  "$SYNQ_URL/api/projects/$PROJECT_ID/cpu-placement"

# Reserve cores 2 and 3 exclusively, with high CPU priority
curl -X PUT -H "Authorization: Bearer $SYNQ_TOKEN" -H "Content-Type: application/json" \
  -d '{"placement":{"cores":[2,3],"exclusive":true,"cpuShares":2048}}' \
  "$SYNQ_URL/api/projects/$PROJECT_ID/cpu-placement"

# Release everything
curl -X PUT -H "Authorization: Bearer $SYNQ_TOKEN" -H "Content-Type: application/json" \
  -d '{"placement":null}' \
  "$SYNQ_URL/api/projects/$PROJECT_ID/cpu-placement"

The response includes an apply report: whether the server was reached, how many containers were updated, which failed, and which containers only pick up a removed memory reservation on their next deploy (Docker cannot remove a reservation from a running container). SYNQ_URL is your panel address (for example https://app.example.com).

On this page