TuBrief
Subscribed Channels
Videos
Community

So verhindern Sie max_connections-Fehler bei der Verbindung von Vercel mit AWS Aurora Postgres

TuBrief Editorial
July 21, 2026
0
Computing/Software

Written with AI assistance from the source video. The video is the authority.

Deutsch한국어EnglishEspañol中文العربيةहिन्दीFrançaisPortuguêsРусскийBahasa Indonesia日本語

Related Video

Ship 26 NYC - Workshop - Erstellung einer Full-Stack-KI-Anwendung mit Vercel und AWS33:34

Ship 26 NYC - Workshop - Erstellung einer Full-Stack-KI-Anwendung mit Vercel und AWS

Vercel

More from the community

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

September 13, 2026

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

September 13, 2026

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

September 13, 2026

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

September 13, 2026

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

September 12, 2026

Apple Won the AI Race

September 12, 2026

Comments (0)

Log in to leave a comment

No posts yet

© 2026 . All rights reserved.

TuBrief
Subscribed Channels
Videos
Community
Log in

So verhindern Sie max_connections-Fehler bei der Verbindung von Vercel mit AWS Aurora Postgres

Die meisten Tutorials für Serverless-Infrastrukturen zeigen nur, wie man ein paar Mal auf Verknüpfen klickt. Das Problem kommt danach: Sobald der Code bereitgestellt ist und auch nur ein wenig Traffic entsteht, bricht die DB-Verbindung zusammen. Sie geraten ins Schwitzen, weil Sie statische Access Keys verwalten müssen, oder Sie erhalten eine Rechnung mit mehreren hundert Dollar für Datenübertragungskosten.

Hier sind die praktischen Engpässe und Lösungen zusammengefasst, die bei der Anbindung eines Vercel-Frontends an ein AWS-Backend auftreten.

1. Setting up Connection Pooling for Vercel and AWS Aurora Postgres

PostgreSQL startet jedes Mal einen neuen Prozess, wenn sich ein Client verbindet. Jeder Prozess verbraucht mindestens 2 MB bis 8 MB Speicher. Da Vercel Serverless Functions bei eingehenden Anfragen zustandslose Instanzen unbegrenzt hochskalieren, wird das max_connections-Limit von Aurora Postgres (100–300 Verbindungen) innerhalb weniger Sekunden erreicht.

Schließlich erscheint der Fehler FATAL: sorry, too many clients already, die CPU-Auslastung der DB erreicht 100 % und der Dienst stürzt ab.

Sie müssen PgBouncer zwischen den Serverless Functions und Aurora platzieren und den Transaction Pooling-Modus aktivieren. Session Pooling hilft nicht, da es Verbindungen 1:1 hält, und Statement Pooling unterstützt keine Multi-Statement-Transaktionen. Transaction Pooling weist die DB-Verbindung nur für die Dauer der Abfragetransaktion zu und gibt sie sofort nach dem COMMIT an den Pool zurück.

Hier ist die Konfiguration für die Datei pgbouncer.ini:

`ini
[pgbouncer]
pool_mode = transaction
max_client_conn = 10000
default_pool_size = 20
reserve_pool_size = 10
max_db_connections = 80

`

  • Aktivieren Sie die Wiederverwendung auf Transaktionsebene mit pool_mode = transaction.
  • Setzen Sie max_client_conn auf etwa 10000 und erhöhen Sie das ulimit -n-Limit des Betriebssystems.
  • default_pool_size ist die Anzahl der Verbindungen, die pro DB-Benutzer und DB-Paar zu Aurora offengehalten werden sollen. Setzen Sie diesen Wert zwischen 10 und 20.
  • Wenn Sie max_db_connections fest auf 80 einstellen, können Sie die tatsächliche Obergrenze der Verbindungen zur Aurora-Instanz erzwungen steuern.

In der Vercel Fluid Compute-Umgebung teilen sich mehrere Ausführungsaufrufe den globalen Scope. Daher müssen Sie den DB-Treiber-Pool im Modulscope deklarieren. Mit dem Paket @vercel/functions und attachDatabasePool werden ungenutzte Verbindungen sauber aufgeräumt, bevor die Funktionsinstanz beendet wird.

`typescript
import { Pool } from 'pg';
import { attachDatabasePool } from '@vercel/functions';

const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 10,
idleTimeoutMillis: 5000,
});

attachDatabasePool(pool);

export default pool;

`

Auch der Connection String sollte nach Umgebung getrennt werden. In der lokalen Entwicklungsumgebung (.env.local) verbinden Sie sich direkt mit dem Aurora-Port (5432) oder verweisen auf den lokalen PgBouncer. In der Produktion (.env.production) hängen Sie den PgBouncer-Port (6432) und den Parameter pgbouncer=true an.

`bash

.env.local (Direct Connection)

DATABASE_URL="postgresql://dbuser:dbpassword@aurora-cluster.us-east-1.rds.amazonaws.com:5432/app_dev?sslmode=require"

.env.production (PgBouncer)

DATABASE_URL="postgresql://dbuser:dbpassword@pgbouncer-proxy.internal:6432/app_prod?sslmode=require&pgbouncer=true"

`

2. Managing IAM Permissions with OIDC Instead of Access Keys

Das direkte Eintragen von AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY in die Vercel-Umgebungsvariablen ist gefährlich. Wenn die Schlüssel durchsickern, wird die gesamte Infrastruktur kompromittiert. Wenn Sie Administratorrechte wie AdministratorAccess vergeben haben, wird die Situation noch dramatischer.

Verwenden Sie OIDC (OpenID Connect). Dabei wird ein von Vercel ausgestelltes, signiertes JWT an die AssumeRoleWithWebIdentity-API von AWS STS gesendet, um temporäre Anmeldeinformationen mit einer Gültigkeit von 1 Stunde zu erhalten. Dadurch entfallen fest codierte Schlüssel komplett.

In der AWS IAM Role Vertrauensstellungspolitik sollten nur die Mindestrechte definiert werden:

`json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.vercel.com/my-team-slug"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.vercel.com/my-team-slug:aud": "https://vercel.com/my-team-slug",
"oidc.vercel.com/my-team-slug:sub": "owner:my-team-slug:project:my-ai-app:environment:production"
}
}
}
]
}

`

  • Registrieren Sie [oidc.vercel.com/my-team-slug](https://oidc.vercel.com/my-team-slug) im IAM Identity Provider.
  • Beschränken Sie den aud-Claim auf Ihre Vercel-Team-URL, um den Zugriff anderer Organisationen zu verhindern.
  • Zielen Sie mit der sub-Claim-Bedingung exakt auf den Projektnamen (my-ai-app) und die Umgebung (production). Dies ist die Schlüsselkonfiguration zur Verhinderung von Confused-Deputy-Angriffen.

Auch die Berechtigungsrichtlinie sollte nur die erforderlichen Ressourcen freigeben. Hier ist ein Beispiel, das nur Zugriff auf einen bestimmten S3-Bucket und das Aufrufen einer Lambda-Funktion gewährt:

`json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RestrictedS3BucketAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-production-ai-assets",
"arn:aws:s3:::my-production-ai-assets/*"
]
},
{
"Sid": "RestrictedLambdaInvocation",
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"arn:aws:lambda:us-east-1:123456789012:function:python-ml-inference-service"
]
}
]
}

`

In Node.js-Code rufen Sie temporäre Anmeldeinformationen mit @vercel/oidc-aws-credentials-provider ab:

`typescript
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
import { awsCredentialsProvider } from '@vercel/oidc-aws-credentials-provider';

const credentials = awsCredentialsProvider({
roleArn: process.env.AWS_ROLE_ARN!,
});

const s3Client = new S3Client({ region: 'us-east-1', credentials });
const lambdaClient = new LambdaClient({ region: 'us-east-1', credentials });

export async function POST(req: Request) {
const body = await req.json();

await s3Client.send(new PutObjectCommand({
Bucket: 'my-production-ai-assets',
Key: inputs/${Date.now()}.json,
Body: JSON.stringify(body),
}));

const lambdaRes = await lambdaClient.send(new InvokeCommand({
FunctionName: 'python-ml-inference-service',
Payload: Buffer.from(JSON.stringify(body)),
}));

return Response.json({
status: 'success',
result: JSON.parse(Buffer.from(lambdaRes.Payload!).toString()),
});
}

`

3. Reducing API Latency Caused by Regional Differences

Wenn Ihr Vercel-Frontend an einem Tokyo PoP läuft und das AWS-Backend in US-East (us-east-1) liegt, kommen bei jeder Anfrage 150 ms bis 250 ms physikalische Latenz hinzu.

Es ist sinnvoll, API-Antworten, die sich nicht häufig ändern, auf Vercel Edge Middleware-Ebene zu cachen, damit der Backend-Aufruf gar nicht erst weitergeleitet wird.

`typescript
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export const config = {
matcher: ['/api/v1/ml-models/:path*'],
};

export function middleware(request: NextRequest) {
const response = NextResponse.next();

response.headers.set(
'Cache-Control',
'public, s-maxage=60, stale-while-revalidate=120'
);
response.headers.set(
'Vercel-CDN-Cache-Control',
's-maxage=300, stale-while-revalidate=600'
);

return response;
}

`

Wenn Sie s-maxage=60, stale-while-revalidate=120 angeben, wird 60 Sekunden lang sofort aus dem Edge-Cache geantwortet. Nach Ablauf des Caches wird bis zu 120 Sekunden lang vorerst die alte Antwort geliefert, während der Cache im Hintergrund aktualisiert wird.

Um Tracing zwischen Diensten zu verbinden, müssen Sie den W3C TraceContext-Standard (traceparent-Header) von OpenTelemetry weiterleiten. Hier ist die Vercel-Konfiguration:

`typescript
// instrumentation.ts
import { registerOTel } from '@vercel/otel';

export function register() {
registerOTel({
serviceName: 'vercel-frontend-service',
instrumentationConfig: {
fetch: {
propagateContextUrls: ['api.my-aws-backend.com', '*.amazonaws.com'],
},
},
});
}

`

Wenn Sie auf der AWS FastAPI-Seite ebenfalls einen OpenTelemetry-Empfänger einrichten, werden Frontend und Backend unter einer einzigen Trace-ID verbunden.

`python
from fastapi import FastAPI
from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

provider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4318/v1/traces"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

app = FastAPI(title="Python ML Service")
FastAPIInstrumentor.instrument_app(app)

@app.get("/api/v1/ml-models/predict")
async def predict():
tracer = trace.get_tracer(name)
with tracer.start_as_current_span("ml_inference_execution"):
return {"status": "completed", "prediction": [0.95, 0.05]}

`

4. Preventing Data Transfer Fees and Unlimited Scaling Costs

Kostenunfälle passieren gewöhnlich an zwei Stellen: Bei Vercels Zusatzgebühren für Fast Data Transfer (über 1 TB kostet jedes weitere GB $0,15) und bei AWS Data Transfer Out (GB für $0,09). Wenn sich dann noch der Traffic häuft und Serverless Functions sowie Lambda gleichzeitig hochskalieren, erreichen die Rechnungen völlig neue Dimensionen.

Hier ist ein Beispiel für eine API-Route, die den Vercel Spend Limit Webhook empfängt und eine Benachrichtigung an Slack sendet. Aus Sicherheitsgründen sollte eine HMAC SHA1-Signaturprüfung durchgeführt werden:

`typescript
import crypto from 'crypto';

export async function POST(req: Request) {
const payload = await req.text();
const signature = req.headers.get('x-vercel-signature');

const expectedSignature = crypto
.createHmac('sha1', process.env.VERCEL_SPEND_WEBHOOK_SECRET!)
.update(payload)
.digest('hex');

if (signature !== expectedSignature) {
return new Response('Invalid Signature', { status: 401 });
}

const event = JSON.parse(payload);

await fetch(process.env.SLACK_WEBHOOK_URL!, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: Vercel Ausgaben-Warnung: Budgetlimit (${event.payload.spendAmount} USD) erreicht.,
}),
});

return new Response('OK', { status: 200 });
}

`

Aktivieren Sie unbedingt diese zwei Sicherheitsnetze:

  1. Aktivieren Sie Pause production deployment in den Vercel-Projekteinstellungen unter Settings > Billing. Selbst wenn der Dienst bei Erreichen des Budgetlimits stoppt, schützen Sie so Ihr Bankkonto.
  2. Begrenzen Sie die Reserved Concurrency (reservierte Gleichzeitigkeit) von AWS Lambda auf etwa 50. Dies verhindert Szenarien, in denen unendlich viele Instanzen entstehen, die Datenbank überlasten und gleichzeitig massive Kosten verursachen.