Refresh Token Rotation With a Previous Pair

Part of the Refresh Token Design series. The Problem With Single Use Single use refresh tokens are the standard advice and the advice is right. A refresh token that works twice is a refresh token somebody can steal and use behind you. The trouble is the failure mode when a response goes missing. A client sends its refresh token. The server rotates, writes the new pair, and answers. The answer never arrives, because the tunnel dropped, the phone changed cell, the laptop lid closed. The client still holds the old token, and the old token is now spent. It retries, gets refused, and the person is looking at a login screen because of one lost packet. ...

June 28, 2026 · 7 min · 1406 words · Sagar Nayak

Your JWT Was Never Stateless

What This is a nine part series on refresh token rotation, session records, and device binding, built around one claim: the JWT in your auth system is not a stateless assertion, and treating it as one is what makes the design complicated. A JWT is three useful properties. It expires on its own, it cannot be modified without invalidating the signature, and it can carry data you put there. That is a good envelope. It is not an authority on whether the person holding it should still be let in. ...

June 21, 2026 · 7 min · 1481 words · Sagar Nayak

Ledger Attachments: Multiple File Upload with Per-File Queues

Part of the Sanchayam series. What The ledger is Sanchayam’s expense and income tracker. Every entry can carry supporting documents stored in S3: receipts, invoices, settlement reports. The first version of the attachment panel accepted one file per trip through the file picker. Adding five receipts to one entry meant opening the picker five times and waiting for each upload to finish before starting the next. The panel now accepts a whole batch in one pick. This post covers how that works: per-file queues, sequential uploads, up-front validation, and retryable failures. ...

June 14, 2026 · 4 min · 847 words · Sagar Nayak

Migrating n8n from SQLite to PostgreSQL

What The n8n instance on our production server stopped processing work. One workflow, a telemetry collector that receives a stream of concurrent webhook calls, had overloaded the database and taken the whole instance down with it. The numbers when we looked: 300+ executions stuck in running state 346 executions in new state that never started 161 executions failed with LockAcquireTimeoutError The UI was slow enough to be unusable The error behind all of it: ...

June 8, 2026 · 5 min · 985 words · Sagar Nayak

Parsing NSE Announcements with DeepSeek

Part of the Sanchayam series. Expands Stage 2 of the corporate actions pipeline. What Sanchayam computes FIFO cost basis and XIRR from historical prices. Prices are fetched by trading symbol. When a company changes its symbol (INFOSYSTCH to INFY) or its name (Hindustan Lever to Hindustan Unilever), a price lookup by the current symbol silently misses every week before the change. The backfill pipeline fixes this with an alias table. One row per symbol-and-name period, so each historical date range is queried with the symbol that was live at the time. Yahoo Finance supplies splits and bonuses. NSE corporate announcements supply name changes, symbol changes, and mergers. ...

June 2, 2026 · 7 min · 1398 words · Sagar Nayak