Das unsichtbare Limit: Wie ein kleiner Parameter unsere Azure PostgreSQL Skalierung ausbremste
Wenn wir eine neue Applikation entwickeln beginnen wir meist mit Ressourcen, etwa Servern oder Datenbanken, die von der Leistung her am unteren Ende des erwarteten Bedarfs sind. Das Schöne an Cloud-Applikationen: Ressourcen lassen sich mit wenigen Klicks skalieren und damit die Leistung verbessern. Und so zahlt man auch erst für die Leistung, wenn sie gebraucht wird.
Need for Speed
Bei einer unserer Applikationen war das kürzlich der Fall: Die Anzahl der Benutzer ist stetig gewachsen, und die Datenbank kam langsam an ihre Grenzen.
Vor allem die CPU, aber auch die Anzahl gleichzeitiger Verbindungen.
Daher haben wir die Datenbank auf das nächste Leistungslevel hochgestuft – konkret von Standard_B1ms auf Standard_B2s.
Kleiner Exkurs: Auf Azure wählt man für die PostgreSQL-Datenbank die sogenannte Compute Size aus. Diese bestimmt die Rechenleistung: Anzahl CPU‑Cores, die Grösse des Arbeitsspeichers sowie die maximale Lese- und Schreibgeschwindigkeit. Diese Parameter können jedoch nicht unabhängig voneinander gewählt werden. Man muss sich dafür aber nicht überlegen, welche Kombination von Rechenleistung und Arbeitsspeicher sinnvoll ist.
Etwas bremst noch
Die Datenbank hatte nun also mehr Leistung, Problem gelöst. Oder so dachten wir. Die Auslastung der CPU war jetzt wie erwartet tief. Aber trotzdem sahen wir weiterhin viele Fehlermeldungen, dass keine weiteren Verbindungen geöffnet werden konnten. Wieso denn das? Gemäss der Dokumentation von Microsoft zu den einzelnen Stufen kann jede grössere Stufe auch mit mehr Verbindungen umgehen. Ein kurzer Blick auf die Metriken zeigt, dass die Anzahl der Verbindungen weit unter dem Maximum von 429 Verbindungen lag, welches die neue Stufe B2s zulassen würde.
Irgendwo muss es also noch eine weitere Limitierung geben.
Nach etwas Suchen haben wir dann den Parameter max_connections in den Einstellungen des Datenbankservers gefunden.
Tatsächlich: Dieser war immer noch auf den Wert der vorherigen Stufe gesetzt.
Die Datenbank selbst erlaubte also viel weniger Verbindungen, als sie gemäss Leistungslevel verarbeiten könnte.
Wir haben die max_connections auf 429 gesetzt – und siehe da: keine weiteren Fehlermeldungen!
Es stellt sich heraus, dass die Datenbankparameter, also auch max_connections, mit den Werten initialisiert werden,
die dem Level entsprechen, mit dem man die neue Datenbank auf Azure anlegt.
Skaliert man dann aber diese Datenbank auf ein höheres Level, dann müssen solche leistungsabhängigen Parameter von Hand nachgeführt werden.
Automatisierte Lösung dank Infrastructure as Code
Für die maximale Anzahl Verbindungen haben wir das direkt automatisiert.
Wir managen unsere Infrastruktur mit OpenTofu, also Infrastructure as Code.
Dort ist nun auch hinterlegt, wie viele Verbindungen wir pro Datenbankstufe zulassen wollen.
Diese Werte sind gemäss den Empfehlungen von Microsoft gesetzt.
Skalieren wir also die Datenbank auf die nächste Stufe, wird auch der max_connections Parameter automatisch angepasst.
Hier ein Auszug aus der OpenTofu Konfiguration, um den max_connections Parameter automatisch anzupassen:
variable "postgres_flex_server_sku" {
type = string
description = "The compute size of the Azure PostgreSQL server"
default = "B_Standard_B2s"
}
resource "azurerm_postgresql_flexible_server" "main" {
name = "mydb"
version = "18"
sku_name = var.postgres_flex_server_sku
# sonstige Konfigurationen...
}
# Setzt den max_connections Parameter basierend auf der gewählten Grösse
resource "azurerm_postgresql_flexible_server_configuration" "max_connections" {
server_id = azurerm_postgresql_flexible_server.main.id
name = "max_connections"
value = local.max_connections_map[var.postgres_flex_server_sku]
}
locals {
max_connections_map = {
"B_Standard_B1ms" = 50
"B_Standard_B2s" = 429
"B_Standard_B2ms" = 859
# and so on…
}
}
Fazit
Wir dachten, das Upgrade würde uns einfach mehr Leistung bringen – und sind prompt über einen limitierenden Parameter gestolpert. Seither wissen wir: Auch in der Cloud gibt es Stellschrauben, die manuell justiert werden müssen. Dank etwas Debugging und einer Prise Automation wird das gleiche Problem bei uns nicht mehr auftreten.