23Articles

All articles

Practical write-ups on the technologies I work with: .NET and C#, SQL Server, AWS, observability, and the apps on this site. Newest first.

RSS feed
  1. 5 min read

    Moving to TypeScript 7: Five Times Faster, and the One Thing That Breaks

    TypeScript 7's compiler is a Go port, and it is fast: type checks five to six times faster on two real projects. What stops the upgrade isn't your code, it's every tool that uses the compiler's API, which 7.0 doesn't ship. Measured on json2types and a game monorepo, with the side-by-side setup that keeps typescript-eslint and compiler-API tests working.

  2. 9 min read

    Weigh to Go: A Weight Diary That Never Leaves Your Browser

    A private, offline weight diary in TypeScript that keeps every weigh-in on your device: IndexedDB with a memory fallback, backups that merge without undoing corrections, a smoothed trend under the daily noise, projections with honest error bands, charts without a chart library, and a Content Security Policy that stops scripts from sending data.

  3. 8 min read

    Inferring C# and TypeScript Types from a JSON Sample

    How json2types turns pasted JSON into C# classes and TypeScript interfaces: keeping the text of every number, merging every sample instead of reading the first, sizing integers exactly and checking decimals against their range, typing dates only when every value is one, choosing names every compiler accepts, and testing the output against the real .NET and TypeScript compilers.

  4. 8 min read

    npm Supply Chain Attacks in 2026: Why Provenance Isn't Enough

    This year's npm attacks published malicious packages with valid provenance, from the projects' own release workflows. What provenance does and doesn't prove, and the defences that would have helped, tried on npm 12: lockfiles, a release-age cooldown, blocked install scripts, and trusted publishing scoped to a reviewed release. Plus the same ideas for NuGet.

  5. 6 min read

    C# 15 Union Types in Practice: Results the Compiler Checks

    C# 15 adds union types and closed hierarchies, so a method can return 'an order, or out of stock, or payment declined' and the compiler makes every caller handle each case. Tried on .NET 11 RC2: what replaces the hand-rolled Result types, what the compiler catches, what JSON does with a union, and the caveats: boxing, default values and switch statements.

  6. 7 min read

    Polly v8 in Practice: Retries, Circuit Breakers and Timeouts That Behave

    Polly v8 replaced policies with resilience pipelines, and Microsoft.Extensions.Http.Resilience made a sensible default one line. What each strategy actually does, measured against a deliberately flaky local server: jittered backoff, a breaker that fails in a hundredth of a millisecond, timeouts that cancel the request, and why the order of strategies matters.

  7. 5 min read

    Testcontainers in .NET: Integration Tests Against the Real Database

    EF Core's in-memory provider passes tests that the real database fails: unique indexes, column lengths, foreign keys and decimal precision are all ignored. Testcontainers starts a real PostgreSQL per test run in about three seconds. The same four tests, both ways, with real timings and a setup that keeps a hundred tests under a second.

  8. 8 min read

    AI Agents in .NET: Tools, a Loop and the Guardrails That Matter

    An agent is a model, a set of tools and a loop. With Microsoft.Extensions.AI that's a few dozen lines of C#. The work is in the guardrails: rules enforced in code, approvals for actions that change things, a cap on the loop, and tests that don't need a model. A support agent built and run against a local model, with its real output.

  9. 8 min read

    Azure Service Bus in Practice: Retries, Dead Letters, Duplicates and Order

    Sending and receiving a message takes five lines. What decides whether a Service Bus system holds up is what happens when a handler fails, a message is malformed, a send is repeated or events must stay in order. Each behaviour here was run against the official Service Bus emulator, with its real output.

  10. 7 min read

    A Neon Shooter on Canvas at 60 fps: Fixed Steps, Pools and Baked Glow

    Drift is an arcade space shooter drawn on an HTML canvas that has to hold 60 fps on an iPhone with hundreds of ships, bullets and particles on screen. The four decisions that make it work: a fixed-step loop, pools instead of allocation, glow baked once instead of every frame, and a performance budget enforced by a test.

  11. 6 min read

    Determinism in Games: Seeds, Forked Streams and Replays

    Why Math.random is banned in my games. Every random draw goes through a seeded generator, so level 37 is the same puzzle on every phone, a daily challenge needs no server, and a whole arcade run can be replayed from its inputs. How seeds, forked streams, fingerprint tests and replays work in practice.

  12. 7 min read

    From Web Game to iPhone App With Capacitor: What It Really Takes

    Arrows is one TypeScript codebase that ships as a website and an App Store app. How Capacitor wraps it, one platform interface for both, ads and consent in the right order, safe areas, and a TestFlight upload from GitHub Actions without a Mac on the desk.

  13. 7 min read

    Decanta: Measuring How Hard a Water Sort Puzzle Is

    More colours don't always make a harder water sort puzzle. Decanta rates every deal by its traps: the share of the moves worth trying that lead to a dead end. How the solver, the trap count and the difficulty bands work, with numbers from the real generator.

  14. 7 min read

    Moat: Generating Logic Puzzles With Exactly One Solution

    Every Moat board has one solution that logic alone reaches, generated on the phone in milliseconds. How: castles first, realms grown around them, border cells moved until every other solution dies, and a human-style solver that rates the difficulty.

  15. 8 min read

    Proving a Casino Game's Math: Exact Fractions and Monte Carlo

    A casino game's return to player has to be right to the last decimal. How the Original Table Games prove every declared RTP twice: exactly, by running the real game over every outcome with BigInt fractions, and by a seeded Monte Carlo run sized to a 99.9% confidence.

  16. 5 min read

    Arrows: Infinite Puzzles Generated on the Phone, From a Seed

    Arrows is a puzzle game for the iPhone and the web with endless levels, a daily challenge, a league and events, and no server. Every board is generated on the device from a seed. Here's how: partition, peel and measure, pixel-art events and a simulated league.

  17. 8 min read

    Diving Into SQL's Hidden Gems: Common Table Expressions (CTEs)

    The WITH clause, or Common Table Expressions (CTEs), is an underused way to structure complex queries. What CTEs are, how to chain them, recursive CTEs, deleting duplicates through a CTE, and what they really do (and don't do) for performance.

  18. 6 min read

    How to Generate Diagrams with Mermaid in ChatGPT

    Diagrams make processes, workflows and data structures easier to follow. How to have ChatGPT write them in Mermaid's text syntax, where to render them, prompts that work, and how to fix the syntax errors that come up.