Skip to content

    The tools I reach for, and what each one is actually for.

    A working list rather than a wish list. It changes when something stops earning its place.

    Azure

    The cloud side of the work, for hosting services and managed databases where running them ourselves would not pay off.

    On-prem and self-hosted

    A lot of what I work on runs on our own servers, so I care about setups that do not assume a cloud provider underneath.

    Kubernetes

    Where services run, in the cloud or on-prem. I can stand up a cluster and deploy to it, not only write the manifests.

    Docker

    Every service ships as a container, so it runs the same on a laptop, in the pipeline and in production.

    draw.io

    For the bigger pictures, like how products talk to each other and where the security boundaries sit.

    Mermaid

    Diagrams as text, kept next to the code in Markdown, so they get reviewed and updated with it.

    C# and .NET

    My main language. I have worked with it from Web Forms through to today's minimal APIs.

    TypeScript

    My other main language, mostly for front ends.

    Python

    For scripts and smaller tools. I use it well enough to get the job done, without calling it a specialty.

    Visual Studio and VS Code

    Visual Studio for heavier .NET work, VS Code for everything else.

    Claude Code and opencode

    Coding agents I use daily, and build workflows around so repeated work runs the same way each time.

    Self-hosted models

    Local models for work that is cheap to check or should not leave the machine.

    GitHub Actions

    Pipelines for build, test and deploy, written to be reused across many repositories rather than copied into each.

    GitLab CI

    The same ideas on GitLab, where that is where the code lives.

    PostgreSQL

    My default relational database when the choice is open.

    SQL Server

    The relational database behind much of the .NET work I have done.

    MongoDB

    For data that is read and written as whole documents, where a fixed schema would get in the way.

    Redis

    Caching and short-lived shared state, so hot reads do not all land on the main database.

    RabbitMQ

    Queues between services, so one can hand off work without waiting on another or failing when it is down.

    Prometheus and Grafana

    Metrics collection and the dashboards and alerts built on top of them.

    Loki and ELK

    Log aggregation, so a problem can be followed across services instead of one machine at a time.

    OpenTelemetry

    Instrumentation for traces and metrics that is not tied to any single backend.