
Integrating Midtrans Snap Payments into a Next.js App
A hands-on guide to wiring Midtrans Snap into Next.js: server-side token creation, the Snap popup, and a webhook that verifies the SHA512 signature key.
Blog
Articles on backend architecture, API design, and database patterns — NestJS, PostgreSQL, and building reliable server-side systems.
40 articles

A hands-on guide to wiring Midtrans Snap into Next.js: server-side token creation, the Snap popup, and a webhook that verifies the SHA512 signature key.

Static vs dynamic QRIS, generating a dynamic QR through a licensed PSP, the MPM flow, webhook handling, NMID onboarding, and 2025 MDR fees — a hands-on Node.js guide.

How I wire up message templates, webhooks, the 24-hour window, and per-message pricing with the official WhatsApp Cloud API for Indonesian apps.

Bun and Node.js are closer than the benchmarks suggest in 2026 — here is where each actually wins in production, from startup to native addons.

SQL-first or schema-first? A hands-on comparison of bundle size, edge support, and migrations for the two ORMs I actually ship on.

How Hono lets me write one Web-Standards API and run it unchanged on Cloudflare Workers, Bun, and Node — plus typed RPC with zero codegen.

Kafka is the reflexive answer to "we need a message log," but for workloads under a million messages per second, NATS JetStream gives you durable streams and solid delivery guarantees with a fraction of the operational cost.

Request-scoped providers look like a one-line fix, but scope bubbles up your whole DI graph and costs latency. Here is how it works and why I reach for AsyncLocalStorage first.

Delete your hand-written API interfaces and generate them from the OpenAPI spec instead — how openapi-typescript and openapi-fetch give you a typed client and catch backend drift at compile time.

How I added distributed tracing to a NestJS API with OpenTelemetry auto-instrumentation — the SDK setup, context propagation, and exporting spans to a collector.

How to move a live PostgreSQL database to a new major version with sub-second downtime using publications and subscriptions — and the sequence, large-object, and DDL gaps that will bite you at cutover if you forget them.

When one-way SSE beats a full WebSocket, how reconnection and HTTP/2 change the math, and how I actually choose per use case.

How I killed a drift-prone ledger table and rebuilt the JID Carwash cash book as a derived Postgres UNION view over payments, expenses, and kasbon.

Why the JID Carwash ERP stores every rupiah as an integer, never a float — and the end-of-day reconciliation bug that made the rule non-negotiable.

How I made carwash POS payment settlement safe against double-taps and network retries using idempotency keys, a Postgres unique constraint, and one guard spec test.

Why I made SUM of an append-only StockMovement ledger the source of truth in my carwash ERP, and treated Product.stockQty as a cache I rebuild.

How I build seller-side middleware that keeps one inventory source of truth across Shopee Open Platform and Tokopedia (TikTok Shop) APIs.

A hands-on backend comparison of Xendit and Midtrans for Indonesian payments — payment methods, fees, DX, and disbursement.

How to rename or restructure a live database column with zero downtime by keeping old and new columns running side by side through a five-step rollout.

Your broker delivers at-least-once, so duplicates are guaranteed. Here is how a processed-messages table turns that into exactly-once effects.

The three PgBouncer pooling modes, the prepared-statement trap that bit me in transaction mode, and how to actually size pool_size for a real app.

How I read PostgreSQL EXPLAIN ANALYZE output: seq scan vs index scan, nested loop vs hash join, buffers, and how to find the node that is actually slow.

When to push derived logic into STORED generated columns, how to index them, and the constraints that bite you in production.

Continuous streaming replication to object storage, point-in-time restore, and the honest limits of single-node SQLite on a VPS.

The license drama split the ecosystem in two. Here is what actually changed, how drop-in the swap really is, and whether it is worth your weekend.

How to coordinate multi-service transactions in NestJS using the saga pattern, orchestration vs choreography, compensating actions, and idempotent step design.

How SELECT FOR UPDATE SKIP LOCKED turns a plain table into a concurrent job queue with no double-processing, and where a real broker still wins.

Reliably publish domain events without dual-write bugs, using an outbox table, a relay poller, and PostgreSQL's row-level locking.

A practical blueprint for webhooks your consumers can actually trust: HMAC signing, at-least-once delivery with backoff, idempotency keys, and a replayable event log.

How to add feature flags to a NestJS backend for percentage rollouts, per-tenant targeting, and kill switches, without letting flag debt pile up.

A practical walkthrough of testing NestJS apps at three layers — mocked-provider unit tests, real-database integration tests, and supertest-driven end-to-end tests.

Ship schema changes without taking your app offline, using the expand-contract pattern with Prisma: backfills, dual-write windows, and safely dropping old columns.

How to enforce tenant isolation inside the database itself with PostgreSQL row-level security, session variables, and tests that actually prove isolation holds.

The mental model most NestJS tutorials skip: decorators just attach metadata, and guards read that metadata back at request time with Reflector. Once that clicks, custom decorators stop feeling like magic.

After rebuilding multi-level approval workflows three times across ERP projects, I extracted the pattern into an open-source TypeScript npm library.

A practical walkthrough of building liveness and readiness probes in NestJS with the official @nestjs/terminus package, wired into real Docker and Kubernetes configs.

Retries, exponential backoff, dead-letter queues, and monitoring: a production blueprint for background jobs with BullMQ, Redis, and NestJS that survives bad days.

Double-charged payments start with a timeout and a retry. How to design idempotent endpoints with idempotency keys, from storage schema to client behavior.

A practical PostgreSQL indexing guide: when B-tree, GIN, BRIN, and partial indexes win, how to read EXPLAIN ANALYZE, and the real numbers behind a 170x speedup.

Bank Indonesia's SNAP (Standar Nasional Open API Pembayaran) is now mandatory for all licensed payment service providers. This guide covers OAuth 2.0 authentication, HMAC-SHA512 request signing, QRIS 2.0 cross-border payments, and practical Node.js implementation patterns for Indonesian fintech developers.