Skip to content

Scaling with process roles

The standard installation runs everything in one lunarpaper container: the web app, the API, real-time collaboration and background jobs. This is the supported setup, and most installations never need to change it.

Running background jobs in a separate worker container can stop heavy exports, document rendering or AI runs from slowing down people using the app. The cost is one more container to run and monitor. Before you split, measure how long pages take to respond and how many jobs are waiting in the queues.

The PROCESS_ROLE setting decides what a container runs:

Role Runs
all Everything. The default.
web HTTP, WebSockets, collaboration and webhooks
worker Queues and schedules

To split the work, run two lunarpaper services from the same image and with the same secrets. Set one to web and the other to worker, and give each its own health check. Never run a worker alongside a container set to all, because both would process the same queues and schedules. The install guides do not include this setup, so treat it as a custom deployment.

A second container doubles the number of database connections. See Database sizing. To undo the split, remove the worker and set the main service back to PROCESS_ROLE=all.

The homepage shows a screenshot of each item people are working on. The container that runs background jobs takes these screenshots with a headless browser built into the image, and the same browser renders dashboard PDF and image exports. Each screenshot takes a few seconds and loads the item the way a reader would, so it costs about as much as one page view.

By default the container takes one screenshot at a time, and an item is photographed again at most once an hour after it changes. This keeps up with most installations. For around 1,000 active people:

  • set CONTENT_CAPTURE_CONCURRENCY to 2 or 3 on the container that runs background jobs;
  • give that container 3 to 4 GB of memory.

Each run asks for as many screenshots as the container can take before the next run, so raising the concurrency is enough.

The Thumbnails page shows whether screenshots are working, how many are waiting and how long the oldest has waited. If screenshots are paused, it says why. If the number waiting keeps growing, raise the concurrency or move background jobs into a worker container as described above.