Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
From Node.js to SQL Server: the mssql Package, Connection Pools, Parameterized Queries and Transactions
Connecting Node.js to SQL Server with mssql means opening the pool once at startup, sending every value as a parameter, writing the order and the stock in one transaction and converting decimal columns to kuruş in SQL. With real output: the float error that turns 19.99 into 1998 cents, 16.6 s vs 0.16 s for 100 queries, SQL injection and LIKE wildcards, the race for the last copy, EREQINPROG and an export streaming a million rows in 139 MB.
Getting an Express API Production-Ready: Configuration, Structured Logging with pino, Health Checks, Graceful Shutdown and Cluster
A production-ready Express API validates its configuration against a schema at startup, writes JSON logs with request ids and redacted secrets using pino, separates liveness from readiness, and on SIGTERM stops new connections and finishes open requests before closing the pool. With real output: an export cut at 22 MB instead of 98 MB, the full file after the fix and a controlled cut on timeout, 503 while draining, PID 1's 10-second wait and a 4-worker cluster.
Security in Express: helmet, CORS, Rate Limiting, JWT Validation and Input Limits
Securing an Express API means adding security headers with helmet, restricting CORS to an origin allow-list, applying a rate limit with trust proxy set correctly, validating JWTs with jose against a pinned algorithm, issuer, audience and lifetime, and checking ownership on every order access. With real output: a limit bypassed through X-Forwarded-For, a CORS setting that reflects every origin, 401 for alg none and algorithm confusion, 404 against BOLA, and prototype pollution.
Testing in Node.js: node:test, Mocking, Coverage and API Tests with supertest
Testing in Node.js needs no extra package: node:test brings describe/it, t.mock.fn and t.mock.method, mock timers and snapshots built in, while supertest calls the Express app end to end with fake repositories without opening a port. With real output: the green tick and red file of assert.rejects without await, 26 tests in 0.2 seconds, stock and BOLA tests, the missing snapshot error and coverage dropping from 80% to 62% once the SQL files are included.
What Changed from Node.js 22 to 26: require(esm), Type Stripping, the Permission Model, Temporal and the New Release Schedule
From Node.js 22 to 26 came require(esm), type stripping, the Permission Model, a global URLPattern and Web Storage; 26 turned Temporal on by default, removed the _stream_* modules and writeHeader, and raised NODE_MODULE_VERSION to 147. With real output: Date and Temporal disagreeing on a delivery date, deprecations caught in CI with --throw-deprecation, an addon built on Node 24 that fails to load on 26, and the yearly Alpha → Current → LTS schedule that starts with Node 27.