Skip to content

Technical Architecture

SLAtus is a self-hosted service status page and SLA management tool. It publishes the current state of your services, incidents and maintenance windows, measures availability against SLA targets, and notifies subscribers.

What runs where

SLAtus consists of two processes built from the same code base and sharing one PostgreSQL database:

Process Entry point Purpose
Web app next start (Docker image: port 3100) Public status page, admin UI, public API routes, server actions, SLA report exports
Worker scripts/worker.ts (pnpm worker) Background jobs: e-mail, SMS, webhook and push delivery, maintenance transitions, uptime checks, cleanup
PostgreSQL 16 Docker Compose (dev: port 5433) Single source of truth for all state

Info

The web app and the worker must both run in production. Without the worker, notifications are queued but never delivered, and scheduled checks never run. The web app only starts with SESSION_SECRET set (see Auth & security).

Technology stack

  • Framework: Next.js 16 (App Router), React 19, TypeScript in strict mode
  • UI: Tailwind CSS 4, shadcn/ui components built on Base UI (not Radix), Lato font via next/font
  • Data: PostgreSQL 16, Drizzle ORM on postgres.js, schema in lib/db/schema.ts
  • Background jobs: pg-boss (PostgreSQL-backed queues and schedulers)
  • Validation: Zod 4 for all form and API input
  • Integrations: nodemailer (SMTP), Resend, Twilio (via fetch), web-push (VAPID), pdf-lib (SLA report PDF export), exceljs (SLA report Excel export)
  • i18n: next-intl for the public UI (English and German). The language is a site-wide setting (settings.language), without language routing. The admin UI is English only.
  • Tests: Vitest (unit and integration), Playwright (end-to-end)
  • Package manager: pnpm 12 (version pinned via packageManager in package.json), Node.js 26

Two areas, one code base

  • Public area (app/(public)/): status page /, history, service detail, badge, legal pages, subscription flows. Pages are rendered dynamically on each request and are not cached. <html lang> follows settings.language.
  • Admin area (app/admin/(dashboard)/): protected by role-based guards, see Auth & security. The admin area and the API documentation at /api-docs are marked as an English subtree (lang="en").

The detailed directory layout and the layering rules are described in Structure & stack.

Key design principles

  • Event-based history. Status changes are stored as time windows, not as daily snapshots. Uptime, availability and SLA figures are derived from these windows. See Status model.
  • One entry point for status changes. Manual changes in the admin UI, the API routes and the uptime checker go through applyComponentStatusChange, which runs in a transaction with a row lock. The exceptions are described in the status model.
  • Frozen SLA reports. Once an SLA monthly report is confirmed, its numbers are stored as a snapshot and no longer change when plans or targets change. PDF and Excel exports are generated from this snapshot on every request, in the time zone stored in the snapshot.
  • Fail-closed notifications. A notification is only sent if its template row exists and is enabled. Mail-only types such as double_optin are never sent over webhook, SMS or push.
  • Secrets encrypted at rest. SMTP passwords, API keys, Twilio tokens, webhook secrets and VAPID private keys are encrypted with AES-256-GCM.