Zum Inhalt

Skalierung

Umgezogen

Die konkreten Sizing-Profile (Klein/Mittel/Groß/XL), die Pipeline-Ampel und das Anwenden neuer Worker-/Postgres-/Redis-Werte findest du jetzt unter Admin → System → Ressourcen → Leistung — siehe Ressourcen. Diese Seite bleibt als konzeptioneller Leitfaden: wann reicht ein größeres Profil, wann brauchst du mehr?

Wann skalieren?

Anzeichen, dass die aktuelle Größe nicht mehr reicht:

  • Pipeline-Ampel unter Ressourcen → Leistung steht auf gelb oder rot
  • Die RAM-Verteilung unter Ressourcen → RAM zeigt einen Dienst (meist die Datenbank) dauerhaft nahe am Server-Limit
  • Neue Check-Ergebnisse kommen sichtbar verzögert im Frontend an

Erste Reaktion: ein Sizing-Profil höher wählen (siehe Ressourcen → Leistung). Das deckt die meisten Fälle ab, ohne dass du einzelne .env-Variablen von Hand anfassen musst.

Vertikal vs. horizontal

Pfad Vor- / Nachteil
Vertikal — größeres Sizing-Profil, mehr RAM/CPU am Server Einfach (ein Klick + Container-Neustart), kein Architektur-Umbau, irgendwann hardware-limitiert
Horizontal — mehrere API-Container, externe Datenbank/Redis Mehr Komplexität, dafür Wachstum weit über einen einzelnen Server hinaus

Empfehlung: erst vertikal bis zur größten sinnvollen Server-Konfiguration skalieren (XL-Profil, 16 GB+ RAM). Erst danach horizontal denken.

Externalisieren (Postgres / Redis)

Bei sehr großen Setups kann es sinnvoll sein, Postgres oder Redis aus dem Compose-Stack zu nehmen und einen dedizierten oder managed Dienst zu nutzen. Grober Ablauf:

  1. Externe Instanz aufsetzen (gleiche Postgres-Major-Version, TimescaleDB-Extension installiert)
  2. Daten migrieren (Dump aus dem eingebauten Backup einspielen)
  3. Verbindungs-Variable in der .env auf die externe Instanz umstellen
  4. Den entsprechenden Dienst aus dem eigenen Compose-Stack entfernen

Dieser Pfad ist nicht offiziell durchgetestet — vorher unbedingt an einer Test-Instanz durchspielen, inklusive eines vollständigen Restore-Drills.

Verbindungen zwischen nginx und API/Receiver

Seit Oktober 2026 hält nginx die Verbindungen zur API und zum Receiver offen und verwendet sie für weitere Anfragen wieder (Keepalive), statt für jede Anfrage eine neue TCP-Verbindung aufzubauen. Bei vielen Agents und Collectors spart das spürbar Rechenzeit. Wird ein Container neu erzeugt (Update, Neustart), findet nginx dessen neue Adresse nach wenigen Sekunden von selbst.

Zurückschalten (ohne Downgrade, ohne Änderung an der Compose-Datei):

cd /opt/vesana
docker compose -f docker-compose.prod.yml exec nginx touch /etc/nginx/ssl/vesana-upstream-keepalive.off
docker compose -f docker-compose.prod.yml restart nginx
# falls aktiv, ebenso: agent-gateway, nginx-admin

Danach öffnet nginx wieder für jede Anfrage eine eigene Verbindung, wie vor Oktober 2026 — im Log des Containers steht Upstreams: direkt. Wieder einschalten: die Datei löschen (rm statt touch) und die Container neu starten. Die Datei liegt im ssl-Volume, das alle nginx-Container teilen; sie überlebt Updates. Dieser Weg wirkt auf jeder Installation.

Mit der Compose-Datei ab Oktober 2026 geht es alternativ über die .env: VESANA_NGINX_KEEPALIVE=off eintragen und docker compose up -d ausführen. Auf Installationen mit einer älteren Compose-Datei kommt diese Variable nicht im Container an — dort wirkt nur der Datei-Weg oben.

Wann zurückschalten: wenn nach einem Update vereinzelt 502-Antworten auftreten, obwohl API und Receiver laufen, oder wenn ein eigener Aufbau zwischen nginx und den Diensten (Proxy, Firewall) offene Verbindungen kappt.

Startet nginx mit den Keepalive-Einstellungen nicht (etwa ein selbst gebautes Image mit einem nginx älter als 1.27.3), schaltet der Container von selbst auf die bisherige Variante zurück und schreibt eine Warnung ins Log.

Durchsatz-Verbesserungen und ihre Notschalter

Seit Oktober 2026 verarbeitet Vesana mehr Ergebnisse pro Kern. Jede dieser Änderungen lässt sich ohne Downgrade und ohne .env-Änderung auf das vorherige Verhalten zurückstellen — per SQL in der Datenbank der Instanz:

INSERT INTO system_settings (key, value) VALUES ('<schlüssel>', '<wert>')
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value;
Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
ingest_batch_transaction_enabled false Der Worker schreibt die Ergebnisse eines gelesenen Pakets in einer gemeinsamen Datenbank-Transaktion statt je Anfrage einzeln. Wirkt nach spätestens einer Minute. Wenn im Diagnose-Log häufig result_batch_fallback steht oder Ergebnisse spürbar verzögert ankommen.
worker_processes 1 Anzahl der Verbraucher-Prozesse im Worker-Container (Standard: einer je 4 Kerne, höchstens 4). Wirkt beim nächsten Start des Worker-Containers. Wenn der Server knapp an Arbeitsspeicher ist oder die Datenbank „too many clients" meldet.
receiver_auth_cache_enabled false Der Receiver merkt sich gültige Anmeldungen von Agents und Collectors bis zu 60 Sekunden, statt jede Anfrage in der Datenbank zu prüfen. Ein Widerruf (Token entfernt, Host oder Mandant gelöscht oder deaktiviert) wirkt trotzdem nach spätestens einer Sekunde. Der Schalter wirkt nach spätestens 30 Sekunden. Wenn ein widerrufener Agent oder Collector weiter Ergebnisse abliefert.
receiver_collector_rate_limit_by_results false Ein Collector wird nach der Zahl seiner Ergebnisse begrenzt (Standard 120.000 je Minute) statt nach Anfragen (120 je Minute). Agents bleiben bei 120 Anfragen je Minute. Wirkt nach spätestens 30 Sekunden. Wenn ein einzelner Collector den Receiver überlastet.
receiver_collector_results_max Zahl Obergrenze der Ergebnisse je Collector und Minute, wenn nach Ergebnissen begrenzt wird. Wirkt nach spätestens 30 Sekunden. Um einen Collector gezielt zu drosseln, ohne die Begrenzung ganz umzustellen.
collector_check_concurrency 16 Wie viele Checks ein Collector (auch der Aktive Collector) gleichzeitig ausführt. Nicht gesetzt oder 0 = nach Kernen (unter 4 Kernen 16, sonst 16 je Kern, höchstens 256); höchstens 1024. Unabhängig davon laufen je Zielgerät und für lokale Scripts (api_script, Plugins) höchstens 16 Checks gleichzeitig. Wirkt beim nächsten Config-Abruf des Collectors (Aktiver Collector nach Sekunden, sonst nach bis zu einer Minute), sobald der Collector auf der Version mit dieser Änderung läuft. Wenn Zielgeräte unter gleichzeitigen Abfragen leiden oder der Collector-Rechner knapp an Arbeitsspeicher ist.
anzeige_teilergebnisse_enabled false Startseite, Mandanten-Übersicht, Hosts-Seite, Karte, Standorte und Mandanten-Liste rechnen ihre Zahlen aus Zwischenergebnissen je Mandant, die sich alle Nutzer und offenen Tabs teilen. Jede Änderung (neues Ergebnis, ACK, Downtime, Check anlegen, Gerät deaktivieren …) macht das Zwischenergebnis ihres Mandanten sofort ungültig — die Seite zeigt nach einer eigenen Aktion wie bisher gleich den neuen Stand. Die Hosts-Seite und die Karte fragen beim automatischen Aktualisieren nur noch, ob sich etwas geändert hat, statt jedes Mal alle Geräte zu laden. Ausgeschaltet rechnet jede Anfrage wieder frisch und die Hosts-Seite lädt bei jedem Aktualisieren alle Geräte. Wirkt sofort, ohne Neustart. Wenn eine Übersicht eine andere Zahl zeigt als die Fehlerübersicht oder das Host-Detail, wenn eine Änderung auf der Hosts-Seite erst nach dem Neuladen erscheint, oder wenn im Diagnose-Log status_teilergebnis_abweichung steht.
anzeige_teilergebnisse_max_age_seconds Zahl, 1–30 (Standard 5) Höchstens so viele Sekunden gilt ein Zwischenergebnis, auch wenn sich nichts geändert hat — eine Sicherheitsgrenze, kein Takt. Selten nötig; kleiner stellen, wenn bei status_teilergebnis_abweichung bis zur Klärung jede Zahl so frisch wie möglich sein soll (oder den Schalter oben ausschalten).

Unabhängig davon gilt: Der Worker löscht aus der Ergebnis-Warteschlange nur noch, was er bereits verarbeitet hat. Nach einem Neustart oder Ausfall des Workers gehen keine wartenden Ergebnisse mehr verloren. Ein Eintrag, der über zehn Minuten immer wieder scheitert, landet sichtbar in den Dead-Letters statt die Warteschlange zu blockieren.

Hintergrund-Prüfungen bei vielen Checks

Seit Oktober 2026 suchen die Hintergrund-Prüfungen — überfällige Checks („No Data“), Wartungsfenster, Erreichbarkeit der Geräte, Agent offline, nachgeholte Alarme und Eskalationen — nur noch die betroffenen Checks statt bei jedem Durchlauf alle. Das Ergebnis ist dasselbe. Vesana prüft das selbst: beim ersten Durchlauf nach einem Start und danach stündlich rechnet es zusätzlich den bisherigen Weg. Weicht etwas ab, nimmt der Durchlauf das bisherige Ergebnis und schreibt watcher_abgleich_abweichung ins Diagnose-Log.

Jede Gruppe lässt sich einzeln zurückstellen (gleiche SQL-Form wie oben, Wert false, wirkt im nächsten Durchlauf, also nach spätestens einer Minute):

Schlüssel Betrifft
watcher_index_stale_enabled Checks ohne neue Ergebnisse werden „No Data“
watcher_index_downtime_enabled Wartungsfenster beginnen und enden (der Ablauf befristeter ACKs ist davon unabhängig)
watcher_index_reachability_enabled Erreichbarkeit der Geräte (Ping-Hinweise, Agent-Herzschlag)
watcher_index_dead_agent_enabled Agents, die sich nicht mehr melden
watcher_index_suppressed_replay_enabled Unterdrückte Alarme, die nachgeholt werden
watcher_index_escalation_backfill_enabled Eskalationen für Alarme, die schon vor einem Neustart bestanden

Wann zurückschalten: wenn im Diagnose-Log watcher_abgleich_abweichung steht (der Eintrag nennt die Gruppe) oder ein Check sichtbar falsch steht — er bleibt grün, obwohl keine Ergebnisse mehr kommen, oder hängt nach dem Ende eines Wartungsfensters weiter auf „Downtime“. Dann den Schalter dieser Gruppe auf false setzen und den Fall über den Feedback-Knopf melden.

Sofort prüfen, ohne etwas zu ändern:

docker compose exec api python -m api.app.cli.watcher_abgleich

Die Ausgabe nennt je Gruppe, ob bisheriger und neuer Weg übereinstimmen; bei einer Abweichung endet der Befehl mit Exit-Code 1.

Drei weitere Einträge im Diagnose-Log gehören dazu: downtime_flag_reconciled (ein Check stand ohne laufendes Wartungsfenster auf „Downtime“ und wurde zurückgesetzt), stale_eingaben_repaired (die gespeicherte „No Data“-Schwelle eines Checks passte nicht mehr zu seinem Intervall und wurde nachgetragen) und watcher_takt_ueber_sperre (ein Durchlauf dauerte länger als vorgesehen — ein Zeichen, dass die Datenbank an ihre Grenze kommt).

Beim Update auf diese Version legt die Datenbank vier kleine Indizes, zwei Spalten und eine kleine Tabelle an und füllt die Spalten einmal; bei sehr vielen Checks dauert das Update dadurch einige Sekunden länger.

Config nur bei Änderung

Agents, Collectors und der Aktive Collector holen ihre Konfiguration in festen Abständen beim Server ab (Agent alle 5 Minuten, Collector jede Minute, Aktiver Collector alle 5 Sekunden). Bisher baute der Server sie dabei jedes Mal vollständig neu. Seit Oktober 2026 antwortet er „unverändert", solange sich für den jeweiligen Agent oder Collector nichts geändert hat — Aufträge (Netzwerk-Scans, Netzsuchen, „Jetzt prüfen") kommen trotzdem in jeder Antwort mit. Eine Änderung an einem Check, Gerät, Profil, Script oder an den Freigaben erreicht den Agent bzw. Collector weiter beim nächsten Abruf; eine Änderung am eigenen Gerät erreicht einen Agent schon mit dem nächsten Lebenszeichen (spätestens 20 Sekunden).

Das gilt nur für Agents und Collectors, die die neue Version fahren — ältere bekommen weiter die vollständige Konfiguration wie bisher.

Zur Sicherheit holt jeder Agent und Collector einmal pro Stunde die vollständige Konfiguration. Weicht sie von dem ab, was er hatte, obwohl der Server „unverändert" gemeldet hatte, steht im Diagnose-Log ein Eintrag config_drift (mit den betroffenen Checks bzw. Geräten), und die Admin-Übersicht nennt den Grund. Die frische Konfiguration gilt ab da sofort.

Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
config_delta_enabled false Ausgeschaltet antwortet der Server wieder bei jedem Abruf mit der vollständigen Konfiguration. Wirkt nach spätestens 5 Sekunden, ohne Neustart. Wenn im Diagnose-Log config_drift oder config_version_failed auftaucht, oder eine Änderung einen Agent oder Collector nicht erreicht.

Agent bündelt unveränderte Ergebnisse

Bisher schickte ein Agent seine Ergebnisse alle 5 Sekunden, sobald eines anstand — bei vielen Agents der größte Teil aller Anfragen an den Server. Seit Oktober 2026 schickt er alles, was etwas bedeutet, weiterhin sofort (im gewohnten 5-Sekunden-Takt): jedes Ergebnis, das nicht OK ist, jeden Statuswechsel, das erste Ergebnis eines Checks, „Jetzt erheben", Checks mit kurzem Intervall und Checks, deren Status der Server selbst beurteilt. Nur unveränderte OK-Ergebnisse wartet er bis zu 30 Sekunden ab und schickt sie gesammelt. Alarme und Entwarnungen kommen dadurch nicht später an; ein unveränderter Messwert steht in Graphen und Listen höchstens 30 Sekunden später (im Verlauf zu seiner Messzeit).

Logs schickt ein Agent in diesem Modus alle 30 Sekunden statt alle 5 Sekunden. Öffnest du die Live-Ansicht der Logs eines Geräts, schickt sein Agent wieder im 5-Sekunden-Takt, solange die Ansicht offen ist — die ersten Zeilen kommen nach dem Öffnen nach spätestens 30 Sekunden, danach wie gewohnt.

Das gilt nur für Agents, die die neue Version fahren; ältere schicken weiter wie bisher. Kommt ein Statuswechsel doch einmal gesammelt (später als 10 Sekunden nach der Messung) an, steht im Diagnose-Log ein Eintrag result_change_late. Ein Einzelfall direkt nach vesana-agent test am Gerät ist erklärbar (der Testlauf schickt an der laufenden Instanz vorbei).

Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
result_batching_window_s 0 Wie lange ein unverändertes OK-Ergebnis höchstens wartet (Standard 30, höchstens 60). 0 = jedes Ergebnis im 5-Sekunden-Takt wie bisher. Wirkt beim nächsten Config-Abruf des Agents (spätestens nach 5 Minuten; sofort mit „Jetzt erheben"), ohne Neustart. Wenn im Diagnose-Log result_change_late wiederholt auftaucht oder Werte spürbar verzögert erscheinen.
agent_log_flush_s 0 Takt, in dem Agents Logs schicken (Standard 30 Sekunden, mindestens 5). 0 = Takt der Log-Konfiguration wie bisher (5 Sekunden). Wirkt beim nächsten Config-Abruf des Agents. Wenn Logs ohne Live-Ansicht zu spät erscheinen oder die Live-Ansicht nicht schnell genug wird.
### Lebenszeichen von Agents und Collectors

Agents melden sich alle 20 Sekunden beim Server, Collectors alle 30 Sekunden („Herzschlag"). Bisher schrieb jeder Herzschlag mehrere Zeilen in die Datenbank. Seit Oktober 2026 hält der Server das Lebenszeichen im schnellen Zwischenspeicher (Redis) und schreibt es alle 15 Sekunden gesammelt in die Datenbank. Für dich ändert sich nichts: „zuletzt gesehen", Offline-Meldungen, Host-down-Alarme und die Verfügbarkeits-Balken zeigen dasselbe wie vorher. Neu ist nur, dass ein noch andauernder Ausfall eines Agents oder Collectors im Verfügbarkeits-Balken schon nach gut fünf Minuten erscheint, nicht erst bis zu einer Stunde später.

Ist Redis nicht erreichbar oder wurde es geleert (etwa nach einem Neustart ohne gespeicherte Daten), schreibt der Server die Lebenszeichen vorübergehend wieder direkt in die Datenbank — kein Agent und kein Collector gilt deshalb als offline. Im Diagnose-Log steht dann edge_liveness_redis_unavailable bzw. edge_liveness_restored.

Stündlich rechnet der Server die Ausfälle zusätzlich auf dem bisherigen Weg nach und vergleicht beide Ergebnisse. Weicht etwas ab, steht im Diagnose-Log edge_outages_schatten_abweichung, und die Admin-Übersicht nennt den Grund. Steht der Abgleich mit der Datenbank länger als zwei Minuten, meldet sie edge_liveness_mirror_stale (scheitert ein Abgleich, edge_liveness_mirror_failed) — die Herzschläge werden dann bis auf Weiteres wieder einzeln geschrieben, es geht nichts verloren.

Collectors ab dieser Version halten sich beim Herzschlag an den Takt, den der Server vorgibt (heute 30 Sekunden); ältere bleiben bei 30 Sekunden.

Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
edge_liveness_redis false Ausgeschaltet schreibt jeder Herzschlag wieder direkt in die Datenbank, und Ausfälle werden wieder stündlich ermittelt. Wirkt nach spätestens 10 Sekunden, ohne Neustart; Aus- und Wiedereinschalten erzeugt keine Schein-Ausfälle. Wenn im Diagnose-Log edge_outages_schatten_abweichung oder edge_liveness_mirror_stale auftaucht, wenn Agents oder Collectors fälschlich als offline gelten, oder wenn Redis dauerhaft knapp an Speicher ist.

Mehrere Aktive Collectors

Reichen die Kerne eines Aktiven Collectors nicht mehr, teilen sich mehrere die aktiven Checks — jeder Check gehört genau einem, fällt einer aus, übernehmen die anderen nach 2 Minuten. Wie man einen hinzufügt und was der primäre zusätzlich macht: Aktiver Collector.

Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
active_collector_sharing_enabled false Aus: nur der primäre Aktive Collector prüft, weitere bekommen keine Checks. Wirkt nach wenigen Sekunden. Wenn Checks auf einer anderen Maschine nicht laufen oder im Diagnose-Log ac_result_not_responsible auftaucht.
collector_native_ping_enabled false Ping-Checks aller Collectors laufen über einen ICMP-Socket statt über das Programm ping. Aus: wieder über das Programm. Wirkt beim nächsten Config-Abruf. Wenn Ping-Werte nach dem Update anders aussehen.

Mehrere API-Prozesse und die Hintergrundarbeit

Die Web-API nutzt seit Oktober 2026 mehrere Prozesse, wenn die Maschine es hergibt: einen je 4 Kerne und je 4 GB Arbeitsspeicher, höchstens 8. Unter 8 Kernen oder unter 8 GB bleibt es bei einem Prozess wie bisher. Die Datenbank-Verbindungen der API (DB_POOL_SIZE + DB_MAX_OVERFLOW, zusammen standardmäßig 30) bleiben insgesamt dieselben: die Prozesse teilen sie sich, der Prozess mit der Hintergrundarbeit bekommt davon eine Reserve von 10.

Alles, was im Hintergrund läuft — Alarm-Hochstufung, Eskalation, Ausfall- Erkennung, Wartung, Berichte-Zeitpläne, Status-Seiten, Backups —, fährt trotzdem genau ein Prozess, der „Leiter". Die Prozesse vereinbaren das über Redis; fällt der Leiter aus, übernimmt ein anderer nach höchstens etwa 17 Sekunden, bei einem geordneten Neustart sofort. Das gilt auch mit der Compose-Datei einer älteren Version und im Split-Container-Modus (der Admin-Container fährt nie Hintergrundarbeit).

Ob die Hintergrundarbeit läuft, zeigt die Admin-Übersicht in der Kachel Hintergrundarbeit: welcher Prozess Leiter ist, wie viele API-Prozesse laufen und ob eine Aufgabe steht. Steht eine Aufgabe länger als ihr üblicher Takt (etwa die Alarm-Hochstufung über zwei Minuten) oder führt gar kein Prozess, nennt die Übersicht den Grund. Im Diagnose-Log (Kategorie Wartung) stehen dann hintergrund_stillstand, hintergrund_ohne_leiter, leiter_verloren oder hintergrund_aufgabe_abgestuerzt; eine abgestürzte Aufgabe startet nach einer Minute von selbst neu.

Login-, 2FA- und Step-Up-Begrenzungen zählen für alle Prozesse gemeinsam in Redis. Ist Redis nicht erreichbar, gelten dieselben Grenzen im Speicher jedes Prozesses (Diagnose-Log rate_limit_speicher_ausgefallen) — der Schutz bleibt bestehen.

Schlüssel Wert für „wie vorher" Was es tut Wann zurückschalten
api_processes 1 Anzahl der API-Prozesse. Nicht gesetzt oder auto = nach Kernen und Arbeitsspeicher wie oben. 1 heißt: genau ein Prozess ohne Leiter-Wahl, die Hintergrundarbeit startet sofort wie vor dieser Version. Eine Zahl ab 2 erzwingt so viele Prozesse. Wirkt beim nächsten Start des API-Containers (docker compose restart api). Mit der Compose-Datei ab dieser Version geht dasselbe über API_WORKERS=1 in der .env und docker compose up -d (eine ältere Compose-Datei reicht die Variable nicht in den Container). Wenn die Admin-Übersicht hintergrund_ohne_leiter oder wiederholt leiter_verloren meldet, wenn der Server knapp an Arbeitsspeicher ist, oder wenn die Datenbank „too many clients" meldet.

Anschluss