node

Simple concurrency limiter for batch operations

Unbounded Promise.all is a great way to overload your DB (or a third-party API). I use a small concurrency limiter so I can process batches efficiently while keeping backpressure. This is especially useful for migrations, backfills, and webhook replay

JWT access + refresh token rotation (conceptual)

A single long-lived JWT is a liability: if it leaks, it’s valid until it expires and revocation is hard. I use short-lived access tokens and longer-lived refresh tokens, and I rotate refresh tokens on every use. Rotation means that if an attacker stea

Response compression (only when it helps)

Compression can dramatically reduce payload sizes for JSON and HTML, but it also costs CPU. I enable it with sane defaults and avoid compressing already-compressed content (like images). Compression can also hurt streaming responses and SSE, so I disa

Request ID + structured logging (Express + pino)

Debugging distributed requests is miserable without a stable request id, so I generate it once at the edge, echo it back via x-request-id, and attach it to every log line with a child logger. I keep this intentionally boring because it delivers 80% of

Cron scheduling with node-cron (with guard)

Periodic jobs are common (cleanup, digests, rollups), and it’s easy to accidentally run them on every instance in production. In local dev, in-process node-cron is fine. In production, I either run a dedicated worker or add a guard so only one instanc

Transactional outbox in Node (DB write + event)

The moment you split ‘write to DB’ and ‘publish to a queue’ into two independent operations, you create a place to lose data. Publish first and a DB failure means consumers act on something that never happened. Write first and a publish failure means

OpenTelemetry tracing for Node HTTP

Once services talk to other services, logs alone don’t tell you where time goes. I like OpenTelemetry because it’s vendor-neutral: export to Honeycomb, Datadog, Tempo—whatever your team uses. I keep the initial setup minimal: instrument http, express,

Postgres connection pooling with pg + max lifetime

After getting burned by long-lived connections that slowly accumulate bad state (or get killed by the network) and then explode during peak traffic, I got strict about pg pooling. I keep the pool size small per instance and scale horizontally instead

Safe markdown rendering (remark + rehype)

Markdown is the sweet spot for user-generated content: expressive enough, but not a full HTML editor. The danger is letting raw HTML slip through. I use remark to parse markdown, then rehype to render HTML, and I disable raw HTML unless I have a sanit

Prometheus metrics for request latency

During an incident, the first question is usually ‘is it getting worse?’, and log lines don’t answer that well. Prometheus-style metrics make it easy to track rates and percentiles over time. I instrument request duration as a histogram and label by m

HTTP keep-alive agent for outbound calls

Creating a new TCP/TLS connection for every request is slow and it adds load on both sides. For high-traffic services calling a small set of upstreams, keep-alive reduces latency and CPU dramatically. I configure an https.Agent with sensible maxSocket

Testing Express routes with Supertest + Jest

Route tests give me fast feedback about the API contract without needing a full browser. I structure the app so I can import an app instance without binding a port, then use supertest to make requests. The key detail is determinism: stub time and rand