Thinking
Technical articles on AI, development tools, cloud architecture, and software engineering.
Infrastructure as code does not mean Terraform. CDK, Pulumi, and the question that actually decides it
Somewhere around 2019, "infrastructure as code" became a synonym for Terraform in most conversations, the way "search" means Google. It i...
Queues without Kafka: SQS, EventBridge, and the one place we actually needed a stream
Every platform reaches the moment where a request does too much. The checkout handler sends an email, updates the search index, notifies the warehouse, recor...
Rate limiting: at the edge, in the gateway, or in the app? Three layers, three jobs
"Add rate limiting" is a one-line ticket that hides three different problems. Someone is hammering the login route from one IP: that's abuse, and y...
Health checks that lie: six ways your service says "ready" when it isn't
A health check is a contract between your application and the thing that routes traffic to it. The router asks "can you take a request?" and the ap...
Backups you've never restored aren't backups. A restore drill, timed.
Every AWS data store has backups turned on by default or by a checkbox. Aurora keeps automated backups. DynamoDB has point-in-time recovery. S3 has versionin...
An incident runbook for a team without on-call
Big companies have on-call rotations, incident commanders, severity matrices and a tooling budget to match. A team of three has a group chat and whoever's aw...
Rotating the database password without downtime: the thing you've been putting off
Everyone agrees the database password should rotate. Almost nobody's does, and the reason isn't laziness. It's that the first time you try, something breaks:...
WAF for a Next.js app: the managed rules that block legitimate traffic, and what we did about them
Turning on AWS WAF in front of a web application is one CDK construct and a checkbox's worth of managed rule groups. It's also, in our experience, guaranteed...
Secrets in CDK: Secrets Manager, Parameter Store, and never anything in the template
A CloudFormation template is a text file. It's stored by CloudFormation, it's in cdk.out on every developer's disk, it's in the CI logs from the last synth, ...
Reserved, Savings Plans, or nothing: when a one-year commitment is actually worth it at small scale
AWS will give you up to 72 % off compute if you promise to keep paying for it for three years. The number is real and it's in every cost-optimisation checkli...
NAT Gateway is the most expensive line you don't see
It isn't on the bill. Not as "NAT Gateway", anyway. It's under EC2-Other, a usage type called NatGateway-Hours next to another called NatGateway-By...
Zero-downtime deploys aren't a platform feature. They're a schema-migration discipline.
Every container platform will tell you it does zero-downtime deployments. App Runner, Fargate, Cloud Run, Kubernetes: they all start new instances, wait for ...
Dev, staging and prod from day one: why a team of three shouldn't wait
"We'll separate environments later, when we have users." We've heard that sentence from every small team we've worked with, and we've said it ourse...
You don't need Kubernetes. You need a good Dockerfile and a place to run it.
Every few months a team of three to five engineers asks us whether they should move to Kubernetes. The application is a web front-end, an API, a couple of wo...
What managed observability really costs at 100 GB a day: Datadog, Grafana Cloud, self-hosted
The observability bill is the one that surprises people twice. The first time is when it arrives and it's a third of the compute bill. The second is a year l...
Alerts that don't know which cloud they run in
Every cloud sells you alarms. CloudWatch Alarms, Azure Monitor alert rules, Cloud Monitoring alerting policies: each one is preconfigured, each one is a few ...
Your traces shouldn't know which cloud they run in either
We made the case that application logs shouldn't be owned by the cloud: the app emits, an agent stamps the cloud onto it, a neutral backend stores it. Logs w...
Same tag, no deploy: why cdk deploy with an unchanged image does nothing, and the 300-line script we wrote around it
Two stories about the same deploy pipeline, told together because the second exists because of the first. The first is a bug that isn't a bug: we rebuilt a c...
CloudWatch data protection policies: masking PII before it lands in your logs
A support engineer asked for a debug log on one API route, "just for a week", to chase a bug in address validation. The log line was the whole requ...
Aurora Serverless v2 after six months: the 0.5 ACU floor and the auto-pause myth
Aurora Serverless v2 is sold with one sentence: pay for the database capacity you use, scaled in fractions of a second. Six months of running it in productio...
The CloudFormation 500-resource limit, and how we split a stack without losing data
cdk deploy failed with a message we'd never seen: Template format error: Number of resources, 503, is greater than maximum allowed, 500. Nothing in the diff ...
GitHub OIDC instead of access keys: one deploy role per AWS account, zero secrets in CI
There is a long-lived AWS access key in your GitHub repository secrets. It was created by whoever set up the first pipeline, it has AdministratorAccess becau...
Preview environments per pull request on AWS, without Vercel
Code review has a ceiling. A reviewer can read a diff and reason about it, but they can't click on it. For a product with a UI, the most useful review commen...
The AWS bill of a three-person startup, line by line
Everyone publishes architecture diagrams. Nobody publishes the invoice. That's a shame, because the invoice is where the architecture becomes honest: the ser...
Your logs shouldn't know which cloud they run in
It's 02:40 and the order pipeline is dropping events. The API runs on EKS. The worker that enriches orders moved to GKE last quarter because the ML team live...
AWS App Runner after six months in production: an honest review
We've been running three Next.js applications on AWS App Runner since March 2026, across dev, staging and production accounts, for a client platform with rea...
The day CloudFormation deleted our App Runner services: a post-mortem and the four safety nets we added
On 30 April 2026, a single cdk deploy run from a laptop deleted every App Runner service in our dev environment. No data was lost, nobody outside the team no...
Three AWS accounts, one CDK codebase: how we keep dev, staging and prod from contaminating each other
Most of the AWS articles on this blog so far have been guides: what a service does, how to set it up, what it costs. This one is different. It documents a re...
How We Build Cloud & DevOps — Reliable Infrastructure That Scales
AWS, Azure, Docker, CI/CD pipelines. We set up your infrastructure for reliability, security, and auto-scaling.
Deploying Containerized Applications on AWS ECS Fargate: A Practical Guide
Running containers in production demands reliable orchestration, seamless scaling, and minimal operational overhead. AWS Elastic Container Service (ECS) with...