Skip to main content
Starting in v0.19, Figranium protects its host from running more Chromium processes than it can handle. A resource monitor measures memory and CPU, a concurrency limit is derived from those numbers, and an execution queue holds extra runs until capacity frees up. This page explains each part, how they interact, and how to tune them for your deployment.

Resource monitor

How memory, cgroup limits, and CPU load are measured.

Concurrency limit

How many runs can execute at once on your host.

Execution queue

How extra runs wait, and when they are rejected.

Tuning

Environment variables and recommended settings.

How it fits together

Every execution request passes through a single gate before a browser is launched:
  1. The gate checks the latest resource snapshot. If the host is not under pressure and fewer runs are active than the concurrency limit, the run starts immediately.
  2. Otherwise, the run joins the end of a first-in, first-out (FIFO) queue.
  3. When a run finishes, or the monitor sees resources change, Figranium takes a fresh snapshot and starts queued runs in order until the limit is reached or pressure returns.
  4. If the queue is full, or a run waits too long, the request is rejected with 503 RESOURCE_CAPACITY_EXCEEDED.
  5. Once running, a non-headful execution is stopped if it exceeds the execution timeout and returns 504 EXECUTION_TIMEOUT.

What goes through the gate

Scheduled runs share the same queue as API and editor runs. If a scheduled run is rejected because capacity is exceeded, it is recorded as a failed execution in the history and the schedule continues to its next run.
Rate limiting is applied before the gate. A request that exceeds DATA_RATE_LIMIT_MAX is rejected with 429 without entering the queue. See Configuration.

Resource monitor

The resource monitor starts when the server boots and samples the host every RESOURCE_PROBE_INTERVAL_MS (30 seconds by default). Figranium also takes a fresh sample every time a run finishes. Each sample records:

Container-aware memory

In Docker and other container runtimes, the host’s total memory is misleading: a container limited to 2 GB on a 64 GB server should behave like a 2 GB machine. Figranium reads Linux cgroup memory limits directly, supporting both cgroup v1 and v2. It walks from the process’s own cgroup up to the root and uses the smallest limit it finds. This covers nested cgroups and limits changed at runtime with docker update --memory. If no limit is set, the host values are used.

Memory reserve

Figranium keeps a memory reserve free for the operating system, the Node.js server, and the database. The reserve is the larger of:
  • RESOURCE_MEMORY_RESERVE_MB (default 512)
  • 15% of total memory

Pressure

The host is considered under pressure ("Busy") when either condition is true:
  • Available memory is below the reserve.
  • CPU load is at or above RESOURCE_CPU_THRESHOLD (default 0.9).
Otherwise, pressure is "Normal". While the host is under pressure, no new runs start, even if there are free slots. Runs already in progress continue. New requests go to the queue.
Pressure counts all memory use on the host or container, not just Figranium’s browsers. Another process using a lot of memory can pause the queue.
On Windows hosts, Node.js does not report a load average, so CPU load is always 0 and only the memory check applies.

Automatic concurrency limit

The concurrency limit is the maximum number of executions that can run at the same time. Figranium derives it from total memory and CPU count: The 768 MB figure is the memory budgeted for each Chromium execution. The limit is never lower than 1 and never higher than 4 unless you set it yourself.

Examples

On hosts with 6 GB or more, the CPU count often decides the limit, because one core is kept for the server itself. A 6 GB machine with 2 CPUs runs one execution at a time. Add a CPU or set MAX_CONCURRENT_EXECUTIONS if you want more.

Overriding the limit

Set MAX_CONCURRENT_EXECUTIONS to a positive integer to replace the automatic limit. Pressure checks still apply: the queue pauses when memory or CPU is under pressure, even below your limit.
.env
Each Chromium execution can use 500 MB to 1 GB of memory, more with video recording or heavy pages. Setting the limit above what your host can hold can lead to browser crashes (Target closed) or ENOMEM errors. See Host Specifications.

Execution queue

Runs that cannot start immediately wait in a FIFO queue. They start in the order they arrived.

When queued runs start

Figranium tries to start queued runs:
  • When a run finishes. A fresh resource sample is taken first.
  • When the monitor sees a change. On each probe, if available memory or total memory changed by 128 MB or more, CPU load changed, or the container limit changed, the queue is checked again.
If the host is under pressure at that moment, nothing starts and the queue waits for the next check. Otherwise, queued runs start until the concurrency limit is reached.

Queue limits

HTTP behavior while queued

A queued API request keeps its HTTP connection open until the run starts and finishes. From the caller’s point of view, a queued request is simply a slow request. The worst case is the queue timeout plus the execution timeout (25 minutes with the defaults).
Set your HTTP client’s timeout longer than the time you expect runs to wait and execute. If your client disconnects, Figranium frees that run’s slot right away. The browser work may keep going in the background, so the host can briefly run more than the limit.

Rejection response

When the queue is full or a run times out in the queue, Figranium responds with:
Retry-After (in seconds) and retryAfterMs are both set to the queue timeout. Treat them as an upper bound: capacity often frees up sooner. For retry logic, use exponential backoff capped at the Retry-After value, or poll GET /api/health and retry when queued drops below maxQueue.

Shutdown

When the server shuts down, every waiting run is rejected with RESOURCE_CAPACITY_EXCEEDED so callers are not left hanging. The queue lives in memory and does not survive a restart; callers must resubmit.

Execution timeout

Once a run starts, EXECUTION_TIMEOUT_MS (default 900000, 15 minutes) limits how long it can run. When the timeout is reached, Figranium asks the runner to stop and responds with:
The response has status 504. The run’s slot is released so the next queued run can start. Headful runs have no execution timeout, because they are interactive sessions you control. They still take a concurrency slot while active.

Memory safeguards for results

Large results are also bounded so that a single run cannot exhaust server memory:
  • Extraction workers have bounded output and heap size. An oversized extraction fails for that run only.
  • Execution history records are capped at 256 KB each (MAX_PERSISTED_EXECUTION_BYTES). Larger results are stored with the HTML and data replaced by a truncation notice and only the first 20 log lines kept. See Execution Logs.
  • Retention deletes captures, recordings, and execution history older than the configured period (7 days by default). See Automatic Retention.

Monitoring

GET /api/health includes a protection object with the current state. It does not require authentication, so you can use it from load balancers and uptime monitors.
The same object is returned by GET /api/settings/system. See REST API.

What to watch

  • pressure stays "Busy": the host is short on memory or CPU. Check availableMb against reserveMb and cpuLoad against your threshold.
  • queued grows steadily: runs arrive faster than they finish. Add capacity, spread out schedules, or shorten tasks.
  • active is below maxConcurrent while queued is above 0: the queue is paused by pressure, not by the limit.

Tuning for your deployment

Keep the defaults. Figranium runs one execution at a time and queues the rest. If you use video recording or visit heavy pages, raise the reserve so the queue pauses earlier:
.env
Allow a deeper queue and longer waits so bursts are absorbed instead of rejected:
.env
Staggering cron times by a few minutes is usually more effective.
The automatic limit tops out at 4. On a machine with plenty of memory and cores, set a higher limit and let the pressure checks guard against overload:
.env
Raise the execution timeout for tasks that crawl many pages or wait for slow downloads:
.env
Other processes raise CPU load and can keep the queue paused. Raise the threshold slightly, or give Figranium its own container with CPU and memory limits:
.env
The local CAPTCHA model tier is also chosen from memory, but only once at startup. After resizing a host or container, restart Figranium to re-detect CAPTCHA capacity. See CAPTCHA Solving.

Configuration

All execution environment variables.

Host Specifications

Recommended hardware for your workload.

Performance

Make tasks faster and lighter.

Troubleshooting

Fix capacity and timeout errors.