TuBrief
구독 채널
비디오
커뮤니티

Cara Mencegah Error max_connections saat Menghubungkan AWS Aurora Postgres di Vercel

TuBrief 편집팀
2026년 7월 21일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

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

관련 영상

Ship 26 NYC - Workshop - Membangun Aplikasi AI Full Stack dengan Vercel dan AWS33:34

Ship 26 NYC - Workshop - Membangun Aplikasi AI Full Stack dengan Vercel dan AWS

Vercel

커뮤니티의 다른 글

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

2026년 9월 13일

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

2026년 9월 13일

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

2026년 9월 13일

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

2026년 9월 13일

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

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Cara Mencegah Error max_connections saat Menghubungkan AWS Aurora Postgres di Vercel

Sebagian besar tutorial infrastruktur serverless hanya memperlihatkan proses menekan tombol koneksi beberapa kali. Masalah sebenarnya muncul setelah itu. Begitu kode dideploy dan trafik mulai sedikit melonjak, koneksi DB akan meledak, Anda berkeringat dingin karena mengelola Access Key statis, atau menerima faktur senilai ratusan dolar akibat biaya transfer data.

Berikut adalah rangkuman bottleneck praktis dan solusi yang dihadapi saat menghubungkan frontend Vercel dengan backend AWS.

1. Pengaturan Connection Pooling saat Menghubungkan Vercel dan AWS Aurora Postgres

PostgreSQL menjalankan proses baru setiap kali klien terhubung. Setiap proses mengonsumsi memori dari 2MB hingga lebih dari 8MB. Karena Vercel Serverless Functions menambah instans stateless tanpa batas saat ada permintaan masuk, batas max_connections pada Aurora Postgres (100–300 koneksi) dapat terpenuhi hanya dalam beberapa detik.

Pada akhirnya, error FATAL: sorry, too many clients already akan muncul, penggunaan CPU DB mencapai 100%, dan layanan pun mati.

Anda harus menempatkan PgBouncer di antara Serverless Functions dan Aurora, lalu mengaktifkan mode Transaction Pooling. Session pooling tidak membantu karena menahan koneksi secara 1:1, sedangkan statement pooling tidak mendukung transaksi multi-statement. Transaction pooling mengalokasikan koneksi DB hanya selama transaksi kueri berjalan dan langsung mengembalikannya ke pool segera setelah COMMIT dieksekusi.

Berikut adalah standar konfigurasi untuk file pgbouncer.ini.

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

`

  • Aktifkan penggunaan kembali berbasis transaksi dengan pool_mode = transaction.
  • Atur max_client_conn ke sekitar 10000 dan naikkan batas ulimit -n pada OS.
  • default_pool_size adalah jumlah koneksi yang dibuka ke Aurora per pasangan pengguna DB dan DB. Atur di antara 10 hingga 20.
  • Menetapkan max_db_connections secara ketat di angka 80 memungkinkan Anda mengontrol batas atas koneksi aktual yang masuk ke instans Aurora secara paksa.

Dalam lingkungan Vercel Fluid Compute, beberapa pemanggilan eksekusi berbagi cakupan global (global scope). Oleh karena itu, Anda harus mendeklarasikan pool driver DB pada cakupan modul. Menggunakan fungsi attachDatabasePool dari paket @vercel/functions akan membersihkan koneksi idle dengan rapi sebelum instans fungsi dimatikan.

`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;

`

Connection string juga harus dipisahkan berdasarkan lingkungan. Di lingkungan pengembangan lokal (.env.local), hubungkan langsung ke port Aurora (5432) atau arahkan ke PgBouncer lokal. Di lingkungan produksi (.env.production), gunakan port PgBouncer (6432) dan tambahkan parameter pgbouncer=true.

`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. Mengelola Izin IAM menggunakan OIDC sebagai Pengganti Access Key

Menanamkan AWS_ACCESS_KEY_ID dan AWS_SECRET_ACCESS_KEY secara langsung di environment variable Vercel sangat berbahaya. Jika kunci bocor, seluruh infrastruktur Anda bisa terserang. Situasinya akan jauh lebih buruk jika Anda memberikan izin administrator seperti AdministratorAccess.

Gunakan OIDC (OpenID Connect). Metode ini mengirimkan JWT bertanda tangan yang diterbitkan Vercel ke API AssumeRoleWithWebIdentity milik AWS STS untuk mendapatkan kredensial sementara berdurasi 1 jam. Dengan ini, kebutuhan akan kunci ter-hardcode sepenuhnya hilang.

Hanya izinkan hak akses minimal (least privilege) pada kebijakan hubungan kepercayaan (trust relationship policy) AWS IAM Role.

`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"
}
}
}
]
}

`

  • Daftarkan [oidc.vercel.com/my-team-slug](https://oidc.vercel.com/my-team-slug) ke IAM Identity Provider.
  • Batasi klaim aud ke URL tim Vercel Anda untuk mencegah akses dari organisasi lain.
  • Tentukan nama proyek (my-ai-app) dan lingkungan (production) secara spesifik pada kondisi klaim sub. Ini adalah konfigurasi kunci untuk mencegah serangan Confused Deputy.

Kebijakan izin (permission policy) juga sebaiknya hanya membuka sumber daya yang diperlukan. Berikut adalah contoh pemberian izin hanya untuk bucket S3 tertentu dan eksekusi fungsi Lambda.

`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"
]
}
]
}

`

Dalam kode Node.js, gunakan @vercel/oidc-aws-credentials-provider untuk mengambil kredensial sementara.

`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. Mengurangi Latensi API Akibat Perbedaan Region

Jika frontend Vercel berjalan di PoP Tokyo dan backend AWS berada di AS Timur (us-east-1), latensi fisik sebesar 150ms hingga 250ms akan terakumulasi pada setiap kali permintaan bolak-balik.

Untuk respons API yang tidak sering berubah, sangat disarankan untuk melakukan caching pada tingkat Vercel Edge Middleware agar permintaan tidak diteruskan ke backend.

`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;
}

`

Dengan memberikan s-maxage=60, stale-while-revalidate=120, respons akan langsung diberikan dari Edge cache selama 60 detik. Setelah cache kadaluarsa, respons versi lama akan tetap ditampilkan hingga 120 detik ke depan sambil memperbarui cache di latar belakang.

Untuk menghubungkan tracing antar layanan, Anda harus menyebarkan spesifikasi W3C TraceContext dari OpenTelemetry (header traceparent). Berikut adalah konfigurasi Vercel.

`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'],
},
},
});
}

`

Jika Anda memasang penerima OpenTelemetry yang sama pada sisi AWS FastAPI, frontend hingga backend dapat terhubung dalam satu Trace ID tunggal.

`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. Mencegah Biaya Transfer Data dan Biaya Uncontrolled Scaling

Insiden biaya biasanya meledak di dua tempat: biaya kelebihan Fast Data Transfer Vercel (0,15perGBsetelahmelewati1TB)danbiayaDataTransferOutAWS(0,15 per GB setelah melewati 1TB) dan biaya Data Transfer Out AWS (0,15perGBsetelahmelewati1TB)danbiayaDataTransferOutAWS(0,09 per GB). Ditambah lagi, jika Serverless Functions dan Lambda mulai melakukan autoscaling secara bersamaan saat trafik melonjak, nominal tagihan Anda bisa berubah drastis.

Berikut adalah contoh API Route untuk menerima webhook batas pengeluaran Vercel dan mengirimkan notifikasi ke Slack. Verifikasi tanda tangan HMAC SHA1 harus dilakukan agar tetap aman.

`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: Peringatan Pengeluaran Vercel: Batas anggaran (${event.payload.spendAmount} USD) telah tercapai.,
}),
});

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

`

Pastikan untuk mengaktifkan dua fitur keselamatan berikut.

  1. Aktifkan Pause production deployment di Settings > Billing pada proyek Vercel Anda. Walaupun layanan akan terhenti saat batas anggaran tercapai, saldo rekening bank Anda akan tetap aman.
  2. Batasi Reserved Concurrency pada AWS Lambda ke sekitar 50. Ini akan mencegah situasi di mana instans bertambah tanpa batas, menekan DB, dan memicu penagihan biaya secara bersamaan.