---
term: 'Serverless Connection Pooling in verwalteten Datenbanken'
seoTitle: 'Serverless Connection Pooling in verwalteten Datenbanken'
headline: 'Was ist Serverless Connection Pooling?'
slug: serverless-connection-pooling
category: database
shortDefinition: 'Serverless Connection Pooling ist eine Technik, die wenige echte Datenbankverbindungen auf viele kurzlebige Funktionsinstanzen verteilt.'
relatedTerms:
  - multi-tenant-database-architecture
  - serverless-architecture
  - auto-generated-database-apis
  - database-index
contrastsWith:
  - serverless-architecture
faq:
  - question: 'Warum erschöpft Serverless die Datenbankverbindungen?'
    answer: 'Weil zwei Skalierungsmodelle aufeinanderprallen: Serverless-Compute vervielfacht Instanzen pro Anfrage, während eine Datenbank ein festes Verbindungsbudget hält – standardmäßig oft rund 100. Jede Funktionsinstanz öffnet ihre eigene Verbindung, hält sie über Leerlaufzeiten hinweg, und eine Lastspitze, die 500 Instanzen erzeugt, verlangt 500 Verbindungen auf einmal. Die Datenbank weist den Überschuss ab, und unbeteiligte Abfragen beginnen zu scheitern.'
  - question: 'Was macht ein Connection Pooler wie PgBouncer tatsächlich?'
    answer: 'Er sitzt zwischen Ihrem Code und der Datenbank, nimmt Tausende billiger Client-Verbindungen entgegen und multiplext sie über einen kleinen Pool echter Server-Verbindungen. Die Clients glauben, eine Verbindung zu besitzen; in Wahrheit leihen sie sich eine für eine Transaktion oder Session und geben sie zurück. Die Datenbank sieht einen ruhigen, festen Satz von Verbindungen, ganz gleich wie viele Funktionen hochfahren.'
  - question: 'Was ist der Unterschied zwischen Transaction Pooling und Session Pooling?'
    answer: 'Die Dauer der Leihe. Session Pooling weist eine echte Verbindung für die gesamte Session des Clients zu – für jedes Feature sicher, aber ein einziger untätiger Client belegt weiterhin eine Verbindung. Transaction Pooling verleiht die Verbindung nur, solange eine Transaktion läuft, und holt sie danach zurück; das vervielfacht die gemeinsame Nutzung dramatisch, macht aber den Session-Zustand unbrauchbar: Prepared Statements, Session-Variablen und LISTEN/NOTIFY brauchen Sorgfalt oder scheitern.'
  - question: 'Warum schnellen die Verbindungen hoch, wenn Funktionen skalieren?'
    answer: 'Eine Serverless-Plattform bewältigt Nebenläufigkeit, indem sie Instanzen klont, und jeder Klon initialisiert seinen eigenen Datenbank-Client. Verbindungen werden nur innerhalb einer warmen Instanz wiederverwendet, nie über Instanzen hinweg. Nebenläufigkeit 300 bedeutet also 300 Pools der Größe eins – die denkbar schlechteste Form: der gesamte Overhead des Poolings ohne jede gemeinsame Nutzung. Das Auffächern ist strukturell bedingt, kein Fehler in Ihrem Code.'
  - question: 'Wie groß sollte ein Datenbank-Connection-Pool sein?'
    answer: 'Weit kleiner, als die Intuition nahelegt. Der Durchsatz erreicht sein Maximum meist bei einem Pool nahe der tatsächlichen Parallelität der Datenbank – eine verbreitete Faustregel ist die doppelte Kernzahl, angepasst an Wartezeiten auf die Festplatte – und nicht im dreistelligen Bereich. Darüber hinaus erzeugen zusätzliche Verbindungen Konkurrenz und Speicherkosten, ohne Durchsatz zu bringen. Die Aufgabe des Poolers ist genau die, einen kleinen Pool für die Aufrufer unendlich wirken zu lassen.'
  - question: 'Brauche ich mit einem BaaS noch einen Pooler?'
    answer: 'Für Ihren eigenen Verkehr nicht – das ist der Punkt. Ein verwaltetes Backend beendet Client-Anfragen als zustandslose HTTPS-Aufrufe auf der API-Ebene; seine eigene Serverschicht unterhält langlebige, richtig dimensionierte Pools zur Datenbank. Ihre Funktionen und Apps halten überhaupt keine Datenbankverbindungen, das Erschöpfungsszenario verschwindet also, statt nur abgemildert zu werden. Pooler kehren nur zurück, wenn Sie externe Werkzeuge direkt anbinden.'
  - question: 'Welche Nachteile haben Connection Pooler?'
    answer: 'Sie fügen einen Netzwerk-Hop an Latenz hinzu, werden zu einer Komponente, die Sie betreiben und überwachen müssen, und der Transaction-Modus verändert stillschweigend die Semantik – auf die Session bezogene Funktionen verhalten sich nicht mehr wie dokumentiert. Ein einzelner Pooler-Prozess kann unter stoßweiser Last selbst zum Engpass werden, und eine falsche Dimensionierung verschiebt die Warteschlange nur. Er ist unverzichtbare Infrastruktur, aber eben Infrastruktur.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'PgBouncer features — pooling modes'
    url: 'https://www.pgbouncer.org/features.html'
  - name: 'PostgreSQL connection settings (max_connections)'
    url: 'https://www.postgresql.org/docs/current/runtime-config-connection.html'
  - name: 'Connection pool (Wikipedia)'
    url: 'https://en.wikipedia.org/wiki/Connection_pool'
  - name: 'Serverless Architectures — Mike Roberts (martinfowler.com)'
    url: 'https://martinfowler.com/articles/serverless.html'
cta:
  title: 'Die Verbindungsrechnung ganz überspringen'
  text: 'Auf Back4app sprechen Ihre Clients und Cloud-Code-Funktionen zustandsloses HTTPS mit automatisch generierten APIs, während die Plattform richtig dimensionierte Pools zur verwalteten Datenbank unterhält – kein Pooler zum Deployen, kein max_connections zum Feintuning, kein Erschöpfungsvorfall um 3 Uhr nachts.'
  linkText: 'Kostenlos starten'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-09-29'
translationKey: serverless-connection-pooling
---

**Serverless Connection Pooling ist eine Technik, die wenige echte Datenbankverbindungen auf viele kurzlebige Funktionsinstanzen verteilt.** Es existiert, weil zwei Skalierungsmodelle sich nicht einig sind: [Serverless-Compute](/glossary/de/serverless-architektur/) beantwortet Last durch das Vervielfachen von Instanzen, während eine Datenbank jede Verbindung als teure, speichergebundene Ressource mit harter Obergrenze behandelt. Fügt man beides naiv zusammen, wird aus einer bescheidenen Lastspitze ein Ausfall mit `too many connections`.

## Das Wichtigste in Kürze

| Frage | Antwort |
| --- | --- |
| Die Kollision | Funktionen skalieren durch Klonen; Verbindungen sind gedeckelt und teuer |
| Das Symptom | `FATAL: sorry, too many clients already` während der Spitzen |
| Die Abhilfe | Ein Pooler multiplext viele Clients über wenige echte Verbindungen |
| Der Regler | Transaction Pooling vs. Session Pooling – Teilen vs. Kompatibilität |
| Die BaaS-Antwort | Clients sprechen zustandsloses HTTPS; der Plattform gehört der Pool |

## Der Ausfall, aus Sicht der Datenbank

```sql
-- Was die Datenbank bei einer Serverless-Lastspitze sieht:
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state;
--  active               |   14
--  idle                 |  483     ← von warmen Funktionsinstanzen belegt
SHOW max_connections;    --  100    ← die Grenze, die sie längst gesprengt haben

-- Jede Verbindung ist ein echter Prozess mit echtem Speicherbedarf —
-- darum existiert die Grenze, und darum hilft ihr Anheben nicht.
```

Die Form des Problems: Jede Funktionsinstanz öffnet ihre eigene Verbindung, hält sie über den Leerlauf zwischen den Aufrufen hinweg, und die Zahl der Instanzen bestimmt der Verkehr, nicht Sie. Wiederverwendung geschieht nur *innerhalb* einer warmen Instanz – nie über Instanzen hinweg –, also bedeutet Nebenläufigkeit 300 eben 300 Pools mit je einer Verbindung. [`max_connections`](https://www.postgresql.org/docs/current/runtime-config-connection.html) anzuheben kauft Luft zu echten Speicherkosten und verliert gegen die nächstgrößere Spitze.

Auf einem verwalteten Backend steigt der Anwendungscode ganz aus diesem Kampf aus – SDK-Aufrufe sind zustandslose HTTPS-Anfragen, und kein Client hält jemals eine Datenbankverbindung:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// Inside a serverless function: no driver, no pool, no connection to leak.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
Parse.initialize('APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com';

export async function handler(event) {
  const query = new Parse.Query('Order');
  query.equalTo('status', 'pending');
  query.limit(20);
  const orders = await query.find();  // request returns; nothing stays open
  return orders.map((o) => o.id);
}
// 1,000 concurrent invocations = 1,000 HTTP requests,
// not 1,000 database connections.
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// No driver, no pool, no connection to leak from the client side.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
await Parse().initialize(
  'APP_ID',
  'https://parseapi.back4app.com',
  clientKey: 'CLIENT_KEY',
);

Future<List<String>> pendingOrderIds() async {
  final query = QueryBuilder<ParseObject>(ParseObject('Order'))
    ..whereEqualTo('status', 'pending')
    ..setLimit(20);
  final response = await query.query(); // request returns; nothing stays open
  return response.results!
      .map((o) => (o as ParseObject).objectId!)
      .toList();
}
// A burst of clients = a burst of HTTP requests,
// not a burst of database connections.
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// No driver, no pool, no connection to leak from the client side.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
ParseSwift.initialize(
  applicationId: "APP_ID",
  clientKey: "CLIENT_KEY",
  serverURL: URL(string: "https://parseapi.back4app.com")!
)

let query = Order.query("status" == "pending")
  .limit(20)
query.find { result in
  if case .success(let orders) = result {
    render(orders)                 // request returned; nothing stays open
  }
}
// A burst of clients = a burst of HTTP requests,
// not a burst of database connections.
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// No driver, no pool, no connection to leak from the client side.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
Parse.initialize(
    Parse.Configuration.Builder(context)
        .applicationId("APP_ID")
        .clientKey("CLIENT_KEY")
        .server("https://parseapi.back4app.com")
        .build()
)

val query = ParseQuery.getQuery<ParseObject>("Order")
query.whereEqualTo("status", "pending")
query.limit = 20
query.findInBackground { orders, e ->
    if (e == null) render(orders)  // request returned; nothing stays open
}
// A burst of clients = a burst of HTTP requests,
// not a burst of database connections.
```

## Wie ein Pooler das Auffächern abfängt

```mermaid
flowchart LR
  accTitle: Connection Pooler zwischen Serverless-Funktionen und der Datenbank
  accDescr: Hunderte kurzlebiger Funktionsinstanzen öffnen billige Client-Verbindungen zu einem Pooler, der sie über einen kleinen, festen Satz echter Datenbankverbindungen multiplext und die Datenbank so unterhalb ihrer Verbindungsobergrenze hält.
  F1["Funktion ×500<br/>(Spitze)"] --> P["Pooler<br/>(z. B. PgBouncer)"]
  F2["Funktion ×500<br/>(nächste Spitze)"] --> P
  P -->|"20 echte Verbindungen"| DB[("Datenbank<br/>max_connections: 100")]
  P -. "Clients warten kurz<br/>statt zu scheitern" .-> F1
```

Ein Pooler wie [PgBouncer](https://www.pgbouncer.org/features.html) nimmt Client-Verbindungen zu Tausenden entgegen – jede auf seiner Seite billig – und verleiht echte Server-Verbindungen aus einem kleinen Pool erst dann, wenn Arbeit eintrifft. Die Datenbank sieht zwanzig ruhige Verbindungen; fünfhundert Funktionen glauben, jede habe eine eigene. Übersteigt die Nachfrage den Pool, warten Clients Millisekunden in einer Warteschlange, statt Fehler zu erhalten – ein harter Ausfall wird so zu bescheidener Latenz.

Bei der Dimensionierung des Pools scheitert die Intuition am deutlichsten. Die nutzbare Parallelität einer Datenbank ist durch Kerne und Festplatten begrenzt – der Durchsatz erreicht sein Maximum typischerweise bei einem Pool im niedrigen zweistelligen Bereich, nahe der doppelten Kernzahl, und *fällt* danach, weil weitere Verbindungen Konkurrenz erzeugen. Die Rechnung des Poolers geht auf, weil Serverless-Anfragen kurz sind: Eine Verbindung, die eine Transaktion von 8 ms bedient, bedient deutlich über hundert davon pro Sekunde, sodass zwanzig echte Verbindungen Tausende von Funktionsaufrufen mühelos aufnehmen. Der [Pool](https://en.wikipedia.org/wiki/Connection_pool) ist kein Cache aus Bequemlichkeit; er ist ein bewusst gesetzter Engpass an der Stelle, an der Warten billig ist.

Der entscheidende Regler ist, *wie lange eine Leihe dauert*.

## Transaction Pooling vs. Session Pooling

| Dimension | Session Pooling | Transaction Pooling |
| --- | --- | --- |
| Dauer der Leihe | Die gesamte Client-Session | Eine Transaktion, danach zurückgeholt |
| Faktor der Mehrfachnutzung | Niedrig – untätige Clients belegen Verbindungen | Hoch – ideal für kurze Serverless-Arbeit |
| Prepared Statements | Vollständig unterstützt | Nur über Unterstützung auf Protokollebene, explizit konfiguriert |
| Session-Zustand (`SET`, temporäre Tabellen, LISTEN/NOTIFY) | Funktioniert | Bricht – verschiedene Transaktionen können verschiedene Verbindungen treffen |
| Am besten für | Langlebige Apps, Admin-Werkzeuge, Migrationen | Anfrage/Antwort-Verkehr im Web und in Serverless |

Der Transaction-Modus macht Serverless-Workloads erst tragfähig – eine Funktion, die eine Transaktion von 8 ms ausführt, sollte keine Verbindung über ihre minutenlange warme Lebensdauer hinweg besitzen –, doch er ist nicht umsonst: Alles, was annimmt, "meine Verbindung" bestehe zwischen zwei Anweisungen fort, wird zu einem subtilen Fehler. Die gängige Empfehlung lautet Transaction Pooling für den Anfrageverkehr und eine direkte oder session-gepoolte Verbindung für Migrationen und alles Zustandsbehaftete.

## Typische Anwendungsfälle

- **Serverless- und Edge-Funktionen, die auf SQL zugreifen.** Der kanonische Fall – stoßweise Instanzzahlen gegen ein festes Verbindungsbudget.
- **Viele kleine Services, eine Datenbank.** Zwanzig Services × Standardpools mit zehn Verbindungen = 200 Verbindungen, die niemand eingeplant hat; ein geteilter Pooler bringt die Rechnung wieder ins Lot.
- **[Multi-Tenant-Plattformen](/glossary/de/multi-tenant-datenbankarchitektur/).** Workloads pro Tenant vervielfachen den Verbindungsbedarf; Pooling hält das Budget der geteilten Datenbank durchsetzbar.
- **Lastspitzen auf bescheidenen Datenbanken.** Spitzen am Starttag warten Millisekunden beim Pooler, statt in der Datenbank Fehler zu erzeugen.
- **Die primäre Datenbank während Störungen schützen.** Ein Pool fester Größe ist ein Schott: Außer Kontrolle geratene Clients erschöpfen die Warteschlange des Poolers, nicht den Speicher der Datenbank.

## Sollten Sie einen eigenen Pooler betreiben? Entscheidungsmatrix

| Betreiben Sie einen Pooler, wenn … | Verzichten Sie darauf, wenn … |
| --- | --- |
| Funktionen oder viele Services direkt auf SQL zugreifen | Ein verwaltetes BaaS den Client-Verkehr auf seiner API-Ebene beendet |
| Verbindungsfehler bei Lastspitzen auftauchen | Der Verkehr gleichmäßig aus wenigen langlebigen Servern mit clientseitigen Pools kommt |
| Sie die Datenbank und ihr Budget selbst betreiben | Die Plattform poolt bereits zwischen API-Schicht und Datenbank |
| Tenants oder Teams sich eine Datenbank teilen | Der Workload aus einer App und einem Pool besteht, klar innerhalb der Grenzen |
| Sie eine weitere kritische Komponente betreiben können | Niemand für den Pooler in Rufbereitschaft ist |

Die ehrliche Asymmetrie: Ein Pooler löst die Erschöpfung der Verbindungen; ein verwaltetes Backend *lässt sie verschwinden*. Wenn Clients HTTPS mit [automatisch generierten APIs](/glossary/de/automatisch-generierte-apis/) sprechen, erreicht das Auffächern die Datenbankschicht überhaupt nicht – Pooling findet weiterhin statt, aber als gut erprobte Infrastruktur eines anderen statt als Ihre Komponente.

## Grenzen und Trade-offs

- **Ein Pooler ist eine Komponente.** Er braucht Deployment, Monitoring, Failover und Updates – Sie haben ein Ressourcenproblem gegen ein Betriebsproblem getauscht, zu günstigem, aber nicht kostenlosem Kurs.
- **Der Transaction-Modus verändert die Semantik.** Prepared Statements, Session-Variablen und Advisory Locks verhalten sich nicht mehr wie dokumentiert; die Fehler treten sporadisch und lastabhängig auf – die schlimmste Sorte.
- **Ein zusätzlicher Hop kostet Latenz.** Im Netz typischerweise unter einer Millisekunde, aber er liegt auf dem Weg jeder Abfrage.
- **Der Pooler kann der Engpass sein.** Ein Single-Threaded-Pooler staut unter einer heftigen Spitze eine tiefe Warteschlange; die Obergrenze hat sich verschoben, verschwunden ist sie nicht.
- **Pooling behebt keine langsamen Abfragen.** Es rationiert Verbindungen; eine Abfrage, die ihre Leihe sekundenlang hält, hungert den Pool aus. Schnelle Abfragen – und die [Indizes](/glossary/de/datenbankindex/) dahinter – bleiben der eigentliche Hebel für Kapazität.

## Connection Pooling mit Back4app

Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Seine Architektur beantwortet die Pooling-Frage strukturell: Client-Apps und Cloud-Code-Funktionen stellen zustandslose HTTPS-Anfragen, und die Serverschicht der Plattform – nicht Ihr Code – unterhält langlebige, richtig dimensionierte Verbindungspools zur verwalteten Datenbank. Das Auffächern der Instanzen auf der Compute-Seite übersetzt sich nie in ein Auffächern der Verbindungen auf der Datenbankseite, und genau diese Eigenschaft herzustellen ist der Zweck dieses ganzen Artikels.
