---
title: "Control resources allocated for site"
space: "Cloud"
url: "https://docs.frappe.io/cloud/control-resources-allocated-for-site"
updated: "2026-06-05"
---

## Performance mode toggle

From the site detail page, under **Dangerous Actions**, you can toggle performance mode for a site on a dedicated server.





![Configure compute allocation in Dangerous Actions](https://github.com/user-attachments/assets/1ac674d7-34c7-44e5-9209-efd76c17a776)



### How worker allocation works

## 

Changing the performance mode directly affects the number of workers on your bench. Every active bench on a server gets a proportional share of the server's total worker capacity. This runs automatically via `auto_scale_workers`, which calls `allocate_workers` on each bench.

### Workload score

## 

Each bench gets a [workload score](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L662): the sum of `cpu_time_per_day` from the plan of every active, pending, or updating site on that bench. The server's [total workload](https://github.com/frappe/press/blob/develop/press/press/doctype/server/server.py#L3712) is the sum across all its [benches](https://github.com/frappe/press/blob/develop/press/press/doctype/server/server.py#L3695).

The performance mode controls which plan a site is on, and therefore its `cpu_time_per_day` contribution to the workload score:

- **High performance** → `cpu_time_per_day: 86000`
- **Not high performance** → `cpu_time_per_day: 8000`

### Server RAM budget

## 

Usable RAM is [calculated first](https://github.com/frappe/press/blob/develop/press/press/doctype/server/server.py#L3716), then split between the two worker pools:

```
usable_ram      = max(total_ram - 3000 MB, total_ram × 0.75)
gunicorn pool   = 60% of usable_ram   →  max_gunicorn_workers = pool / 150 MB
background pool = 40% of usable_ram   →  max_bg_workers       = pool / 240 MB
```

150 MB = avg per gunicorn worker (`GUNICORN_MEMORY`). 240 MB = avg per set of 3 background workers (`BACKGROUND_JOB_MEMORY`).

#### Per-bench allocation formula

## 

Each bench gets a share proportional to its workload, [clamped to the release group's configured bounds](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L793):

```
gunicorn_workers   = clamp(min_gn..max_gn,  round(bench_workload / server_workload × max_gunicorn_workers))
background_workers = clamp(min_bg..max_bg,  round(bench_workload / server_workload × max_bg_workers))
```


| Worker type | Default min | Default max |
| ----------- | ----------- | ----------- |
| Gunicorn    | 2           | 36          |
| Background  | 1           | 8           |


These are overridden if the release group has explicit `min/max_gunicorn_workers` or `min/max_background_workers` set. If total server workload is zero, [every bench falls back to the minimums](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L828).

#### Threaded workers

## 

If `gunicorn_threads_per_worker` is set on the bench, the gunicorn count is [reduced after the proportional step](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L809) to keep total concurrency the same while using fewer processes:

```
gunicorn_workers = clamp(1..max_gn, ceil(gunicorn_workers / gunicorn_threads_per_worker))
```

#### Memory limits

## 

When `set_bench_memory_limits` is on, [cgroup limits are set per bench](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L832):

```
memory_high = 512 MB + (gunicorn_workers × 150 MB) + (background_workers × 240 MB)
memory_max  = memory_high + 150 MB + 240 MB
memory_swap = memory_max × 2
```

If `skip_memory_limits` is set on the bench, it gets the server's [maximum possible limits](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L386) instead. When memory limits are off, [all three are set to 0](https://github.com/frappe/press/blob/develop/press/press/doctype/bench/bench.py#L842).