Effiziente MongoDB-Verbindungen in Payload auf Vercel
Wie sich MongoDB-Atlas-Verbindungen für Payload CMS auf Vercel mit dem afterOpenConnection-Hook und attachDatabasePool verwalten lassen, damit Serverless-Funktionen Idle-Verbindungen vor dem Suspend freigeben.
Geschrieben von
Veröffentlicht am
17. April 2026
Zuletzt aktualisiert am
1. Juli 2026
Tags
Payload CMS auf Vercel nutzt den @payloadcms/db-mongodb-Adapter für MongoDB Atlas. In einer serverlosen Umgebung tritt ein wiederkehrendes Fehlermuster auf: Das Connection-Limit des Clusters wird erschöpft, und Anfragen scheitern mit Verbindungsfehlern unter Last – obwohl der Anwendungscode korrekt ist. Dieser Artikel erklärt warum das passiert und wie sich das mit Payloads afterOpenConnection-Hook und Vercels attachDatabasePool lösen lässt.
Warum serverlose Umgebungen MongoDB-Atlas-Verbindungen erschöpfen
MongoDB Atlas begrenzt die Anzahl gleichzeitiger Verbindungen pro Cluster – das Limit hängt vom Cluster-Typ ab. Ein Flex-Cluster (ehemals Shared) erlaubt maximal 500 gleichzeitige Verbindungen, dedizierte Tiers deutlich mehr. Auf serverlosen Plattformen wie Vercel Functions wird dieses Limit schneller erreicht als auf einem langlebigen Server:
- Cold Starts – jeder neue Cold Start erzeugt einen neuen Connection Pool. Jede neue Function-Instanz öffnet einen eigenen Pool. Eine warme Instanz verwendet denselben Pool wieder – der Druck entsteht also durch neue Instanzen, nicht durch jeden einzelnen Request.
- Gleichzeitige Instanzen multiplizieren Pools. Bei Traffic-Spitzen skaliert Vercel horizontal auf viele parallele Function-Instanzen. Jede hält einen eigenen Pool – die Gesamtverbindungszahl beträgt grob Instanzen × Pool-Größe.
- Idle-Verbindungen bleiben offen. Pools halten Verbindungen für Wiederverwendung offen. Ohne Idle-Timeout zählen Verbindungen inaktiver Instanzen weiter gegen das Limit.
- Suspended Functions können Verbindungen leaken. Wenn eine serverlose Funktion zwischen Requests suspendiert, werden ihre offenen Verbindungen nicht sauber freigegeben – genau das Problem, das Vercels Fluid Compute löst (siehe unten).
Pool begrenzen: maxPoolSize und maxIdleTimeMS
Der erste Hebel sind die Connection-Pool-Einstellungen des Treibers, übergeben über connectOptions des Adapters. Das Pooling übernimmt der MongoDB Node.js-Treiber – nicht Payload. Diese Optionen passen nur sein Verhalten an:
db: mongooseAdapter({
url: process.env.MONGODB_URI || '',
// https://www.mongodb.com/docs/manual/administration/connection-pool-overview/
connectOptions: {
// Standard-maxPoolSize ist 100 – weit mehr als eine serverlose Instanz benötigt.
// Mit 10 bleibt `Instanzen × Pool-Größe` auch bei gleichzeitigen Spitzen
// unter dem Atlas-Limit.
maxPoolSize: 10,
// Verbindungen nach 5s Idle schließen, damit suspendierte Instanzen
// sie nicht weiter belegen.
maxIdleTimeMS: 5000,
},
}), -
maxPoolSize: 10– begrenzt Verbindungen pro Instanz. Der Treiber-Standard ist100– für serverlose Instanzen überdimensioniert. Mit10bleiben selbst 50 gleichzeitige Instanzen bei ~500 Verbindungen – an der Grenze eines Flex-Clusters statt weit darüber. An die reale Parallelität anpassen. -
maxIdleTimeMS: 5000– schließt Idle-Verbindungen nach 5 Sekunden. Das gibt Verbindungen von Instanzen frei, die keine aktiven Requests mehr bearbeiten, und reduziert die Steady-State-Verbindungszahl. Der aggressive Wert ist für Serverless bewusst gewählt, wo Instanzen schnell kommen und gehen; auf einem langlebigen Server würde man ihn deutlich höher setzen oder ganz weglassen.
Verbindungen beim Suspend freigeben: afterOpenConnection + attachDatabasePool
Pool-Limits reduzieren, wie viele Verbindungen jede Instanz hält – aber sie lösen nicht das Leaking von Verbindungen beim Suspendieren einer Funktion. Vercels Fluid Compute adressiert das mit attachDatabasePool aus @vercel/functions. Es registriert den Datenbank-Pool im Function-Lifecycle und nutzt waitUntil, um die Instanz kurz am Leben zu halten, bis Idle-Pool-Clients freigegeben wurden – bevor die Funktion suspendiert. Neben MongoDB unterstützt es Postgres, MySQL2, MariaDB, ioredis und Cassandra.
Das Problem mit Payload: attachDatabasePool braucht den zugrunde liegenden MongoClient – und bis vor Kurzem bot der MongoDB-Adapter keinen unterstützten Weg, ihn zu erreichen. Genau das löst der afterOpenConnection-Hook. Verfügbar in @payloadcms/db-mongodb, läuft er direkt nach dem Verbindungsaufbau und übergibt den Adapter, aus dem der Client ausgelesen werden kann:
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { attachDatabasePool } from '@vercel/functions'
// ...
db: mongooseAdapter({
url: process.env.MONGODB_URI || '',
connectOptions: {
maxPoolSize: 10,
maxIdleTimeMS: 5000,
},
// MongoClient an Vercel übergeben, damit Fluid Compute Idle-Verbindungen
// vor dem Suspend freigibt.
// https://vercel.com/docs/fluid-compute
afterOpenConnection: async (adapter) =>
attachDatabasePool(adapter.connection.getClient()),
}), -
attachDatabasePoolerfordert Fluid Compute. Das Release-on-Suspend-Verhalten setztwaitUntilvoraus, das nur auf Vercels Fluid-Compute-Runtime funktioniert. Außerhalb dieser Umgebung ist der Aufruf ein No-op – dieser Schritt ist Vercel-spezifisch.
Wann das nicht reicht – und was sonst hilft
- Es reduziert Ressourcenverbrauch, nicht die MongoDB-Rechnung. Weniger offene Verbindungen sparen Cluster-RAM und halten die Verbindungszahl unter dem Limit, was die Stabilität verbessert. Sie senken Atlas-Kosten nicht direkt – die Preise richten sich nach Tier, Storage und Compute, nicht nach der Verbindungsanzahl.
- Es ist an Vercel Fluid Compute gebunden. Auf anderen Hosts oder Runtimes ist eine andere Connection-Management-Strategie nötig;
attachDatabasePoolhilft dort nicht. - Medien aus Objektspeicher ausliefern. Standardmäßig liefert Payload Medien über seine eigene API-Route aus (
/api/...). Das Durchsuchen der Admin-Medienbibliothek erzeugt dadurch einen Burst gleichzeitiger HTTP-Anfragen ans CMS – jede trifft eine Function-Instanz und belastet den Connection Pool. Werden Bilder und Dateien direkt von S3 / Cloudflare R2 ausgeliefert, umgeht der Browser Payloads API-Route komplett, und diese Anfragen erreichen weder das CMS noch den Pool. Das kann die Peak-Parallelität spürbar senken, wenn Redakteure aktiv im Admin arbeiten. - Überwachen und Lasttests durchführen. Verbindungszahlen via Atlas-Metriken und Vercel-Logs verfolgen und gleichzeitigen Traffic vor Produktiv-Go-live simulieren, damit
maxPoolSizezur realen Last passt. - SSL alert 80 / transiente TLS-Fehler. Ein konkretes Beispiel für einen transienten Fehler:
MongoNetworkError: SSL alert number 80— Atlas schließt eine bestehende Verbindung bei einem internen Ereignis (z. B. Failover oder Maintenance-Restart), der Treiber setzt daraufhin den gesamten Pool zurück (ResetPool), und alle parallel laufenden Requests scheitern mitMongoPoolClearedError.
Fazit
Payload CMS auf Vercel gegen MongoDB Atlas erfordert kein manuelles Kämpfen gegen Connection-Limits. Pool pro Instanz mit maxPoolSize und maxIdleTimeMS begrenzen, dann den afterOpenConnection-Hook nutzen, um den MongoClient an Vercels attachDatabasePool zu übergeben, damit Fluid Compute Idle-Verbindungen vor dem Suspend freigibt. Konfiguration oben als Ausgangspunkt nehmen, Atlas-Verbindungsmetriken unter Last beobachten und die Pool-Größe an den echten Traffic anpassen.