Estimasi Biaya dan Praktik Migrasi Saat Mengadopsi Vercel Workflows
Batasan Timeout Serverless dan Perhitungan Biaya Bulanan
Saat menjalankan SaaS dengan serverless functions, batas timeout 10 hingga 60 detik sering kali menjadi kendala yang tidak terduga. Saat menerapkan pencadangan data skala besar atau pipeline pembuatan media AI multimodal, lingkungan serverless yang ada terus-menerus menghentikan eksekusi kode.
Vercel Workflows mempertahankan tugas tetap berjalan sambil menurunkan konsumsi sumber daya ke nol saat fungsi memasuki status siaga. Untuk memperkirakan biaya, jalankan skrip TypeScript secara langsung guna menghitung pengeluaran bulanan terlebih dahulu. Tentukan jumlah eksekusi harian, jumlah langkah, durasi eksekusi, dan ukuran payload sebagai objek, lalu masukkan ke dalam fungsi penghitungan biaya. Jika melebihi batas 50.000 event per bulan dan batas penulisan 1GB pada paket Hobby, Anda harus bersiap meningkatkan ke paket Pro. Jika dijalankan kurang dari 15.000 kali per bulan, operasi dapat ditangani dalam kredit dasar Pro, sehingga mengurangi biaya dibandingkan mempertahankan infrastruktur Redis yang di-hosting sendiri.
`typescript
interface WorkflowMetrics {
dailyExecutions: number;
stepsPerExecution: number;
avgStepDurationMs: number;
payloadSizeKb: number;
}
function calculateEstimatedCost(metrics: WorkflowMetrics): { totalEvents: number; estimatedCostUsd: number } {
const totalEvents = metrics.dailyExecutions * metrics.stepsPerExecution * 30;
const freeTierEvents = 50000;
const overageEvents = Math.max(0, totalEvents - freeTierEvents);
const costPerThousand = 0.20;
const estimatedCostUsd = (overageEvents / 1000) * costPerThungk?: number;
return {
totalEvents,
estimatedCostUsd: Number(((overageEvents / 1000) * costPerThousand).toFixed(2)):
};
}
`
Prosedur Transisi dari Message Queue ke SDK Workflow
Saat menggunakan BullMQ atau AWS SQS, pembuatan antrean, penerbitan tugas, penerimaan, dan manajemen koneksi Redis semuanya dibuat secara manual. Proses ini membuat kode membengkak secara tidak perlu. SDK Vercel Workflows menghilangkan kode infrastruktur ini melalui arahan tingkat kode.
Migrasi dapat diselesaikan dalam 3 langkah. Pertama, bungkus file next.config.ts dengan wrapper withWorkflow. Kedua, alih-alih proses worker yang ada, gunakan arahan use step untuk menulis tugas individual sebagai fungsi asinkron. Ketiga, abaikan struktur rantai Parent-Child Job yang rumit dan gunakan pernyataan kontrol JavaScript serta fungsi await sleep di dalam use workflow. Dengan hilangnya kode koneksi Redis eksternal, footprint memori aplikasi berkurang dan waktu transisi menjadi lebih cepat.
`typescript
import { workflow } from "@vercel/workflows";
export const { POST } = workflow(async (context) => {
const userId = context.request.payload.userId;
const data = await context.run("fetch-user-data", async () => {
const res = await fetch(https://api.example.com/users/${userId});
return res.json();
});
await context.sleep("wait-for-processing", "10m");
await context.run("finalize-task", async () => {
await db.users.update({ where: { id: userId }, data: { status: "processed" } });
});
});
`
Penanganan Error untuk Menjaga Konsistensi Data dalam Situasi Pemutusan Jaringan
Untuk mencegah kehilangan data saat terjadi kegagalan non-deterministik, sifat error harus dipisahkan terlebih dahulu. Vercel Workflows membedakan dan menangani error sementara (transient) serta error fatal.
Untuk menangkap error dalam suatu langkah, pertama-tama lemparkan RetryableError saat terjadi error berbasis HTTP 429 atau seri 500 guna memicu percobaan ulang (retry) berdasarkan exponential backoff. Kemudian, sertakan logika pemeriksaan kunci unik di dalam langkah yang memodifikasi database untuk mencegah penumpukan data duplikat saat dicoba ulang. Terakhir, hubungkan Vercel Log Drains dengan Sentry untuk melakukan streaming log JSON terstruktur secara real-time. Dengan menerapkan pola ini, status dipulihkan dari titik henti (breakpoint) bahkan dalam situasi pengecualian, sehingga menghilangkan kebutuhan untuk memulihkan data secara manual.
`typescript
import { RetryableError } from "@vercel/workflows";
export async function processPaymentStep(context: any, paymentData: any) {
return await context.run("charge-payment", async () => {
const exists = await db.transactions.findUnique({
where: { idempotencyKey: paymentData.key }
});
if (exists) {
return exists;
}
const response = await paymentGateway.charge(paymentData);
if (response.status === 429 || response.status >= 500) {
throw new RetryableError("Payment gateway overloaded, retrying...");
}
return await db.transactions.create({
data: { idempotencyKey: paymentData.key, amount: response.amount }
});
});
}
`