Eine Website kann sich träge anfühlen, obwohl der Server schnell antwortet. Häufig kostet nicht die eigentliche Anfrage Zeit, sondern der wiederholte Aufbau von TCP- und TLS-Verbindungen. Mit keep alive bleiben Verbindungen für weitere Anfragen nutzbar, und ich zeige, wie das in HTTP, TCP, Reverse Proxies und modernen Hosting-Umgebungen funktioniert.
Die wichtigsten Entscheidungen auf einen Blick
- HTTP-Keep-Alive nutzt eine bestehende Verbindung für mehrere Requests.
- TCP Keepalive prüft, ob eine scheinbar ruhende Verbindung noch erreichbar ist.
- Idle-Timeouts von Load Balancer, Proxy und Anwendung müssen zusammenpassen.
- Zu lange Verbindungen verbrauchen Speicher und können Deployments erschweren.
- Für die Praxis sind Messwerte und Logs wichtiger als möglichst großzügige Timeout-Werte.

Was eine dauerhafte Verbindung tatsächlich offen hält
Bei einer normalen Webanfrage wird zunächst eine TCP-Verbindung aufgebaut. Bei HTTPS kommt zusätzlich der TLS-Handshake hinzu. Ohne Wiederverwendung muss dieser Aufwand für viele einzelne Dateien, API-Aufrufe oder Datenbankverbindungen immer wieder entstehen. Eine persistente Verbindung reduziert genau diese Wiederholungen und kann Antwortzeiten sowie CPU-Auslastung spürbar senken.
HTTP/1.1 verwendet dauerhafte Verbindungen grundsätzlich als Standard, sofern keine Seite ausdrücklich das Schließen verlangt. Der Server darf die Verbindung trotzdem nach einer Leerlaufzeit beenden. Das ist kein Fehler, sondern eine normale Ressourcenentscheidung. In NGINX liegt der Standardwert für den Leerlauf beispielsweise bei 75 Sekunden.
Wichtig ist die Unterscheidung zwischen einer offenen TCP-Verbindung und einer tatsächlich aktiven Anwendungssitzung. Eine Verbindung kann auf Betriebssystemebene noch existieren, während ein Reverse Proxy sie bereits wegen eines Idle-Timeouts geschlossen hat. Genau diese unterschiedlichen Ebenen sorgen in der Praxis oft für scheinbar zufällige Fehler.
Der Ablauf einer wiederverwendeten Verbindung
- Der Client baut eine TCP-Verbindung zum Server oder Load Balancer auf.
- Bei HTTPS wird die TLS-Verbindung ausgehandelt.
- Der Client sendet eine Anfrage und erhält die Antwort.
- Die Verbindung bleibt für einen begrenzten Zeitraum offen.
- Eine weitere Anfrage verwendet dieselbe Verbindung, sofern sie noch gültig ist.
Der Vorteil ist besonders groß bei Seiten mit vielen Ressourcen oder bei APIs mit häufigen, kleinen Requests. Bei einer einzelnen großen Datei ist der Effekt dagegen deutlich kleiner. Ich sehe deshalb keinen Sinn darin, Keep-Alive pauschal auf möglichst lange Werte zu setzen.
HTTP, TCP und Anwendungssignale sind nicht dasselbe
Der Begriff wird in Hosting-Projekten für mehrere Mechanismen verwendet. Sie verfolgen zwar ein ähnliches Ziel, arbeiten aber auf unterschiedlichen Ebenen. Wer diese Ebenen vermischt, sucht bei einem Timeout schnell an der falschen Stelle.
| Mechanismus | Ebene | Aufgabe | Typischer Einsatz |
|---|---|---|---|
| HTTP Keep-Alive | HTTP | Mehrere Requests über eine Verbindung abwickeln | Webseiten, REST-APIs, Reverse Proxies |
| TCP Keepalive | Transport | Erreichbarkeit einer ruhenden Verbindung prüfen | Lange Verbindungen, NAT, Firewall-Erkennung |
| Heartbeat | Anwendung | Aktivität und Zustand einer Sitzung bestätigen | WebSockets, Messaging, eigene Protokolle |
HTTP Keep-Alive
HTTP Keep-Alive verhindert vor allem unnötige Verbindungsaufbauten. Es sendet nicht automatisch regelmäßig Daten, nur damit eine Verbindung aktiv bleibt. Ist die Leitung lange still, kann ein Proxy sie trotzdem schließen. Diese Unterscheidung ist bei langen API-Operationen entscheidend.
TCP Keepalive
TCP Keepalive arbeitet im Betriebssystem und prüft eine inaktive Verbindung mit kleinen Kontrollpaketen. Unter Linux beginnt die Standardprüfung typischerweise erst nach 7200 Sekunden Leerlauf. Danach folgen standardmäßig neun Prüfungen im Abstand von 75 Sekunden. Für Webanwendungen ist das häufig zu spät, weil Load Balancer und Firewalls viel früher aufräumen.
TCP Keepalive ersetzt daher kein Anwendungs-Heartbeat. Wenn ein Dienst alle 30 Sekunden einen gültigen Ping oder eine Statusnachricht senden muss, sollte diese Logik im Protokoll der Anwendung liegen. Ein TCP-Paket beweist nur, dass die Transportstrecke reagiert, nicht dass die Anwendung noch korrekt arbeitet.
Heartbeat bei WebSockets und ähnlichen Diensten
WebSockets bleiben oft minuten- oder stundenlang geöffnet. Hier braucht man normalerweise einen Ping-Pong-Mechanismus auf Anwendungsebene. Ein sinnvoller Startpunkt ist ein Intervall von 20 bis 30 Sekunden, wobei der genaue Wert vom kürzesten Timeout in der Infrastruktur abhängt.
Ich würde den Heartbeat nicht unnötig häufig senden. Ein Intervall von fünf Sekunden erhöht bei vielen Clients die Last, ohne die Zuverlässigkeit automatisch zu verbessern. Besser ist ein klarer Grenzwert, etwa drei ausgebliebene Antworten, bevor die Sitzung als unterbrochen gilt.
Timeouts müssen entlang der gesamten Kette zusammenpassen
Eine typische Anfrage läuft nicht direkt vom Browser zur Anwendung. Dazwischen liegen oft CDN, Firewall, Load Balancer, Reverse Proxy, Container-Netzwerk und Webserver. Jeder dieser Bausteine kann eine eigene Leerlauf- oder Antwortzeitbegrenzung besitzen.
Die wichtigste Regel lautet deshalb Der innere Dienst darf eine Verbindung nicht früher schließen als der davorliegende Proxy. Schließt die Anwendung ihre Verbindung nach 30 Sekunden, während der Load Balancer 60 Sekunden erwartet, kann der Balancer eine bereits unbrauchbare Verbindung wiederverwenden. Das führt häufig zu 502- oder 504-Fehlern.
| Komponente | Beispielwert | Worauf ich achte |
|---|---|---|
| Anwendung | 60 Sekunden | Verbindung sollte kontrolliert beendet werden |
| Reverse Proxy | 75 Sekunden | Etwas länger als der Backend-Wert |
| Load Balancer | 90 Sekunden | Idle-Timeout nicht kleiner als beim Backend |
| Heartbeat | 20 bis 30 Sekunden | Deutlich vor dem kürzesten Timeout senden |
Die Zahlen sind kein universelles Rezept. Bei Streaming, Server-Sent Events oder WebSockets gelten andere Anforderungen als bei kurzen Webseiten-Requests. Für eine normale API ist eine Kette mit abgestuften Werten jedoch ein brauchbarer Ausgangspunkt.
Warum TCP-Pakete einen HTTP-Timeout nicht immer verhindern
Ein Load Balancer entscheidet meist anhand des Datenverkehrs, den er auf seiner eigenen Verbindung sieht. Ein reines TCP-Keepalive kann deshalb zu wenig sein, um einen HTTP-Idle-Timeout zu verhindern. Bei langen HTTP-Anfragen muss die Anwendung gegebenenfalls echte Nutzdaten senden, etwa einen Fortschrittsstatus oder einen Protokoll-Heartbeat.
Bei langen Jobs würde ich trotzdem nicht einfach den Timeout auf mehrere Stunden erhöhen. Robuster ist ein asynchrones Modell. Die API startet den Auftrag, gibt eine Job-ID zurück und der Client fragt den Status ab oder erhält ihn über eine separate Benachrichtigung.
So sieht eine solide Konfiguration im Hosting aus
Die konkrete Einstellung hängt vom Stack ab. Die Prinzipien bleiben jedoch gleich. Ich beginne immer beim tatsächlichen Datenfluss und prüfe danach, welcher Dienst die Verbindung auf jeder Strecke verwaltet.
NGINX als Reverse Proxy
Für Client-Verbindungen steuert keepalive_timeout, wie lange NGINX nach einer Anfrage wartet. Mit keepalive_requests lässt sich außerdem begrenzen, wie viele Requests über dieselbe Verbindung laufen. Ein bewusst gesetztes Limit hilft, den Speicherverbrauch großer Installationen kontrollierbar zu halten.
http {
keepalive_timeout 60s;
keepalive_requests 500;
upstream app_backend {
server app:8080;
keepalive 32;
}
}Der Wert keepalive 32 im Upstream-Block bezeichnet einen Pool wiederverwendbarer Verbindungen pro Worker und ist nicht einfach ein globales Verbindungsmaximum. Bei vielen Workern kann die tatsächliche Anzahl deutlich höher liegen. Genau das wird bei Kapazitätsplanungen oft unterschätzt.
Apache und Anwendungsserver
Apache verwendet unter anderem KeepAlive, KeepAliveTimeout und MaxKeepAliveRequests. Ein Timeout von etwa 5 bis 15 Sekunden kann bei starkem Webverkehr sinnvoll sein, während interne APIs mit hoher Request-Dichte länger profitieren können.
Auch Node.js, Python-Server und Java-Anwendungen besitzen eigene Socket- oder Agent-Einstellungen. Diese müssen nicht nur zum Webserver, sondern auch zum Datenbankpool und zu externen APIs passen. Ein Backend kann schnell antworten und trotzdem an einem erschöpften Pool aus dauerhaft gehaltenen Verbindungen scheitern.
HTTP/2 und HTTP/3
Bei HTTP/2 laufen mehrere Streams über eine TCP-Verbindung. Dadurch ist die Wiederverwendung noch wichtiger, aber ein einzelner Verbindungsabbruch kann mehrere parallele Requests betreffen. HTTP/3 verwendet QUIC über UDP und hat ein anderes Verbindungsmanagement, das grundlegende Prinzip bleibt jedoch gleich: Idle-Zeit, Wiederverwendung und Erreichbarkeit müssen getrennt betrachtet werden.
Ein älterer Header wie Connection: keep-alive ist bei modernen HTTP-Versionen nicht die zentrale Stellschraube. Entscheidend sind die Protokollversion, die Serverkonfiguration und die Timeouts der Infrastruktur. Ich würde deshalb nicht versuchen, HTTP/2 oder HTTP/3 mit HTTP/1.0-Rezepten zu konfigurieren.
Typische Fehlerbilder lassen sich gezielt eingrenzen
Wenn Keep-Alive falsch abgestimmt ist, zeigt sich das selten als klare Fehlermeldung. Häufig treten Probleme nur unter Last oder nach einer bestimmten Leerlaufzeit auf. Ein strukturierter Test spart hier viel Zeit.
Verbindung wird nach einer Pause abgelehnt
Ein Client hält eine Verbindung für wiederverwendbar, obwohl ein Proxy sie bereits geschlossen hat. Beim nächsten Request kommt dann ein Reset oder ein 502-Fehler. In Logs sollte man die Zeit zwischen letzter Antwort und neuem Request mit dem jeweiligen Idle-Timeout vergleichen.
Viele offene Verbindungen verbrauchen Ressourcen
Ein großzügiger Timeout verbessert nicht automatisch die Leistung. Jede offene Verbindung kann Dateideskriptoren, Speicher und Einträge in NAT- oder Firewall-Tabellen binden. Bei zehntausenden Clients sind 60 zusätzliche Sekunden bereits eine relevante Kapazitätsentscheidung.
Timeouts während Deployments
Lange Verbindungen erschweren Rolling Deployments, weil alte Container nicht sofort beendet werden können. Für WebSockets und Streaming brauche ich deshalb eine kontrollierte Drain-Phase. Neue Verbindungen werden auf neue Instanzen gelenkt, während bestehende Sitzungen entweder sauber enden oder nach einer definierten Frist getrennt werden.
Lesen Sie auch: Logfiles verstehen und richtig analysieren im Hosting
Messung statt Bauchgefühl
Ich prüfe mindestens die Anzahl aktiver Verbindungen, Wiederverwendungsraten, Verbindungsfehler, Antwortzeiten und Abbrüche nach Leerlauf. Mit Tools wie curl, ss und den Access-Logs des Proxies lässt sich meist schnell erkennen, ob das Problem auf HTTP-, TCP- oder Anwendungsebene liegt.
-
curl -vzeigt den Verbindungsaufbau und wichtige HTTP-Header. -
ss -sgibt einen Überblick über TCP-Zustände auf Linux. - Proxy-Logs zeigen, ob der Client oder der Upstream die Verbindung beendet hat.
- Anwendungsmetriken zeigen, ob Threads, Event-Loops oder Verbindungspools an Grenzen stoßen.
Eine gute Grundeinstellung beginnt mit dem Verkehrsmuster
Für eine klassische Website mit kurzen Requests ist ein HTTP-Leerlauf von 30 bis 75 Sekunden oft vernünftig. Interne Services mit vielen Folgeanfragen können von längeren Werten profitieren. Bei mobilen Clients, öffentlichen APIs und vielen gleichzeitig verbundenen Nutzern ist ein kürzerer Wert häufig wirtschaftlicher.
Für lang laufende Verbindungen würde ich drei Regeln festlegen. Erstens braucht jede Sitzung eine erkennbare Aktivität oder einen Heartbeat. Zweitens muss der Server tote Clients zuverlässig entfernen. Drittens sollte ein Client nach einem Abbruch mit Backoff neu verbinden, also mit wachsenden Wartezeiten statt in einer engen Endlosschleife.
Mein praktischer Ablauf sieht so aus
- Den kompletten Verbindungsweg vom Client bis zum Backend dokumentieren.
- Alle Idle-, Request- und Response-Timeouts erfassen.
- HTTP-Wiederverwendung, TCP-Prüfung und Anwendungssignale getrennt testen.
- Werte unter realistischen Nutzerzahlen messen.
- Abbrüche, Deployments und Netzwerkausfälle als eigene Szenarien testen.
Die richtige Balance zwischen Tempo und Ressourcen
Keep-Alive ist kein Schalter für maximale Performance, sondern eine Abstimmung zwischen Verbindungsaufwand und Ressourcenverbrauch. Bei kurzen, häufigen Requests bringt Wiederverwendung viel. Bei langen Leerlaufzeiten können dieselben offenen Verbindungen jedoch Speicher, Ports und Proxy-Kapazität blockieren.
Ich würde deshalb mit moderaten Werten starten, die tatsächlichen Abbruchursachen beobachten und erst danach nachjustieren. Entscheidend ist eine konsistente Timeout-Kette, ein passender Heartbeat für lange Sitzungen und ein Monitoring, das nicht nur Antwortzeiten, sondern auch Verbindungszustände sichtbar macht.
Wer diese drei Punkte sauber trennt, vermeidet die meisten typischen Hosting-Probleme und erhält eine Infrastruktur, die sowohl schnell reagiert als auch bei Last und Deployments kontrollierbar bleibt.