# Gunicorn configuration import os # Exactly one worker: APScheduler and the Playwright run-queue live in # process memory, not a shared store — a second worker would duplicate # every scheduled job and run each rule twice. Fine for a low-traffic # single-user admin tool. workers = 1 threads = 4 worker_class = "gthread" bind = "0.0.0.0:" + os.environ.get("PORT", "5000") # Killing a worker here kills the APScheduler jobstore and the run queue # with it (both live in process memory), dropping every pending # verification poll — so requests that wait on browser work bound their # own wait well under this, via scheduler.REQUEST_WAIT_SECONDS (90). timeout = 120 keepalive = 5