project: name: my-healthchecks # used in User-Agent string runner: # How many sites can be healthchecked at the same time. # Each worker opens its own headless browser. 3 is a safe default for a shared VM; # raise it if the host has spare CPU and you have many sites to check quickly. workers: 3 # Record worker utilization, queue depth, and task durations once per minute. # Powers the /workers dashboard page with utilization trends and capacity forecasts. # Disable to skip ~1 DB write per minute if storage is constrained. workerMonitoring: true # How many Lighthouse audits can run simultaneously. # Default 1 — Lighthouse is CPU/RAM intensive and concurrent runs distort each # other's performance scores (network throttling simulation, JavaScript execution # timing). Only raise this if you have dedicated hardware and understand the # trade-off: scores will be less accurate but audits finish sooner. lighthouseWorkers: 1 # Milliseconds to wait between consecutive page requests within a single site. # 0 disables the delay. Useful for sites on weak shared hosting that struggle # with back-to-back headless browser hits. Can be overridden per site in its YAML. pageDelayMs: 0 sitesDir: ./sites # directory containing site YAML files reportsDir: ./reports # directory where Lighthouse HTML/JSON report files are saved logLevel: info # trace | debug | info | warn | error | fatal schedulerTickMs: 1000 # how often the scheduler checks for due tasks (ms) # Delay before the first Lighthouse audit fires after startup. # Healthchecks start immediately; Lighthouse waits this long so the runner isn't # hammering sites with heavy audits right as it comes online (e.g. after a restart). lighthouseStartDelayMs: 30000 # How to spread site checks across the first interval on startup to avoid all sites # queuing simultaneously (thundering herd). Four modes: # # even — sites divided into equal slots across the interval. Deterministic and # guaranteed to not cluster. Worst case: last site delayed by one full interval. # Example: 6 sites × 10 min → checks at 0:00, 1:40, 3:20, 5:00, 6:40, 8:20. # # random — each new task scheduled at a random point within its full interval. # Can still cluster by chance. Worst case same as even. # # capped — random jitter capped at startupJitterCapMs. All sites get their first # check within the cap, with reduced (but not eliminated) clustering risk. # Example: cap 2 min → all 6 sites checked within 2 min, then stay staggered. # # none — all tasks fire immediately (original behaviour, not recommended). # startupJitter: even # Maximum jitter applied when startupJitter is "capped" (milliseconds). # Has no effect when startupJitter is "full" or "none". startupJitterCapMs: 120000 # 2 minutes # Dashboard API — set apiPort: 0 to disable apiPort: 8080 # Retention — how long data is kept in TimescaleDB (requires DATABASE_URL). logRetentionDays: 7 # structured log entries (7 days is usually plenty for debugging) resultsRetentionDays: 180 # healthcheck + Lighthouse result history (6 months) lighthouseReportRetentionDays: 7 # HTML/JSON report files on disk (these are large; keep short) workerStatsRetentionDays: 3 # worker utilization samples (1 row/min; 3 days matches the UI window) healthcheck: # How often to run healthchecks. Per-site YAML can override with intervalMinutes. defaultIntervalMinutes: 10 # How long to wait for a page to fully load before marking it as failed. # Increase for slow sites; decrease to fail fast and free up the worker sooner. defaultTimeoutSeconds: 30 # How long to wait for a single CSS selector to become visible on the page. # This is separate from the navigation timeout above — a page can load but still # have elements that appear late via JavaScript. selectorTimeoutMs: 5000 # If the browser hangs and doesn't respond to a graceful close, it is force-killed # after this many milliseconds to free the worker slot. forceCloseTimeoutMs: 5000 lighthouse: # How often to run a full Lighthouse audit per site. 360 = every 6 hours. # Lighthouse is slow (30–90s per page) and resource-heavy — running it too # frequently on many sites will queue up audits faster than they can complete. defaultIntervalMinutes: 360 # Throttling profile applied during audits. # mobile — simulates a mid-tier Android phone on slow 3G. This is what Google # uses for PageSpeed Insights and is the most representative of real-world # conditions for most sites. Scores will be lower than desktop. # desktop — uses a fast network and no CPU throttling. Use this for dashboards, # admin panels, or sites whose primary audience is desktop users. defaultThrottling: mobile # mobile | desktop desktopWidth: 1350 # viewport width when throttling: desktop desktopHeight: 940 forceCloseTimeoutMs: 5000 # same force-kill safety net as healthcheck watcher: # How long a site YAML file must be unchanged before it is reloaded. # Prevents a half-written file from being parsed mid-save. stabilityThreshold: 250 # ms pollInterval: 50 # chokidar filesystem poll interval (ms) alerting: defaults: # Channel names applied to every site by default. # Omit this key entirely to apply ALL defined channels to all sites. channels: [ops-chat] # Define all alert channels here. Each must have a unique name. # Channels are referenced by name in site YAMLs (alerting.add / alerting.remove). channels: - type: google-chat name: ops-chat # unique name — referenced in site YAML overrides webhookUrl: "https://chat.googleapis.com/v1/spaces/SPACE/messages?key=KEY&token=TOKEN" on: # events this channel handles - site-down - site-recovery - high-memory # RAM > 85% - memory-recovered - high-load # CPU load > 90% of core count - load-recovered # Example: a second channel for critical alerts only (add to defaults.channels to use): # - type: google-chat # name: critical-ops # webhookUrl: "https://chat.googleapis.com/..." # on: [site-down]