Posts

Go Generics in Production: Patterns That Actually Work

Image
Go 1.18 shipped generics in March 2022. I have been using them in production code since mid-2022, and after a year of real-world use, I have developed a clear picture of where generics genuinely improve code and where they add accidental complexity. This post is the practical guide I wish I had when generics landed. What Problem Do Generics Solve? Before Go 1.18, code that needed to work with multiple types had three options: use interface{} and type-assert at runtime (losing compile-time safety), use code generation (maintenance burden), or copy-paste (duplication). None of these are good. Generics provide a fourth option: parametrised functions and types that work across concrete types while preserving compile-time type safety. The canonical examples — a typed Stack, a Map function over slices — are often dismissed as toy problems. But real production code has the same patterns: generic result types, typed caches, repository abstractions, event buses. Let me show you the patte...

ECS Fargate Autoscaling: How We Cut Infrastructure Costs by 35%

Image
When I joined the company the backend ran on a fleet of EC2 instances sized for peak traffic, sitting at 15% CPU utilisation most of the time. Scaling was manual — someone would notice latency going up, SSH into a box to check what was happening, then provision more capacity if needed. Deployments required coordination to drain the load balancer and restart services one by one. Migrating to ECS Fargate with autoscaling was the single biggest infrastructure improvement we made: costs dropped 35%, deployments became zero-downtime, and on-call became less stressful. Why ECS Fargate Over EC2-Backed ECS ECS can run on two launch types: EC2 (you manage the instances) and Fargate (AWS manages the compute). I chose Fargate for three reasons: No instance management : no more AMI updates, no instance type selection, no patching Bin packing is AWS's problem : with EC2-backed ECS you need the right EC2 instance size to fit your tasks efficiently. Fargate handles this transparently. Pe...

SQS Dead-Letter Queues and Visibility Timeout: What I Got Wrong

Image
I spent an embarrassing amount of time debugging an SQS consumer that was processing messages twice and sometimes three times. The root cause turned out to be a fundamental misunderstanding of how visibility timeout, dead-letter queues, and consumer concurrency interact. Here is everything I wish I had known from the start. SQS Delivery Guarantees: At-Least-Once, Not Exactly-Once Before we dive into configuration, the most important thing to internalise: SQS guarantees at-least-once delivery . The same message may be delivered multiple times, even under normal operating conditions — not just during failures. This is not a bug; it is a deliberate design decision that enables SQS to provide high availability and scalability. Your consumer must be idempotent. Visibility Timeout: The Most Misunderstood Setting When you call ReceiveMessage , SQS makes each returned message invisible to other consumers for the visibility timeout duration. If you do not delete the message before the ti...

Graceful Shutdown in Go: The Right Way

Image
Graceful shutdown is one of those things every backend service needs but few teams implement correctly — until something breaks in production. I learned this the hard way when a deployment left in-flight database writes half-committed, causing data inconsistencies that took a full day to resolve. Here is the complete pattern I have settled on for Go services, including the edge cases most tutorials skip. What Happens Without Graceful Shutdown When a container orchestrator (ECS, Kubernetes) wants to stop a task, it sends SIGTERM to the process. By default, most Go servers ignore it — the process keeps accepting new connections, existing requests finish eventually, and the orchestrator gives up and sends SIGKILL , killing everything immediately. Any in-flight HTTP requests, open database transactions, or messages being processed from a queue are abandoned mid-operation. On a busy service this is guaranteed to cause problems. The real damage depends on what your service does: HTT...

Symfony 5 dynamic database connection

Image
The other day I was facing a problem to connect Symfony to multiple databases, there is a way to have multiple database connection in the official documentation but in that method you should define all the databases from the start, which means you can only pick a database that already has defined in your controller, you can't just connect to a database in real time. Sometimes, you may need to specify the connection parameters inside the controller itself, for example, you may want to connect to a database where the database name was specified in the URL or you want to insert data into a different databases where the database connection parameters are inside an other database... It's getting complicated, I know! Let's just say in this blog I will show how to connect dynamically to a database inside the controller. Let's start by creating a new PHP class called DynamicConnection.php and add it inside src folder, we can even create a new folder called...