Skip to content
Al Shakib E Elahi
06Engineering

Every technology choice is a trade. These are the ones I would defend.

Organised by the architectural question each layer answers rather than by logo. A tool with no stated cost is a tool nobody has run in production.

Layers
4
Technologies
17
01Moving work between services

What happens when the receiver is down?

A direct call couples two services in time: both have to be up at the same instant, and the caller inherits the callee's latency and failure. The moment a system has more than a couple of moving parts, that coupling becomes the thing that takes it down. Messaging breaks the timing dependency - the producer's job ends when the message is durable, not when the consumer is finished.

  1. Kafka

    Solves

    A durable, replayable, ordered log. Consumers read at their own pace and can rewind, so a bad deploy is recoverable by reprocessing rather than by restoring a backup.

    Costs

    Operationally heavy. Partitions, consumer groups and retention are decisions you have to make correctly up front, and ordering only holds within a partition.

  2. gRPC

    Solves

    Typed, binary service-to-service calls with a schema both sides compile against, so contract drift becomes a build error instead of a runtime surprise.

    Costs

    Not browser-native without a proxy layer, and harder to inspect with ordinary HTTP tooling when something goes wrong at 2am.

  3. Redis

    Solves

    Sub-millisecond shared state - cache, rate limiting, locks, ephemeral queues, and the pub/sub fan-out behind multi-instance real-time.

    Costs

    It is memory. Treating it as a database is how teams discover their durability assumptions were wrong.

02Where the business logic lives

How long will this be readable?

Runtime choice is mostly a choice about what the language refuses to let you do. A strict type system trades keystrokes for a class of bug that never reaches production. A permissive one trades that safety for speed of first delivery. Both are correct answers to different questions - the mistake is picking without knowing which question you are answering.

  1. Rust

    Solves

    Memory and concurrency safety enforced at compile time. Data races are a compiler error, not a rare production incident that reproduces once a month.

    Costs

    The borrow checker charges its cost up front, in development time. Justified where correctness and predictable latency matter more than iteration speed.

  2. Spring Boot

    Solves

    A mature, opinionated backbone for JVM services - transactions, security and data access as boring, well-understood infrastructure.

    Costs

    Convention plus reflection means the framework does a lot you did not write, which is excellent until you have to debug it.

  3. ASP.NET Core

    Solves

    Long-running worker services and typed Web APIs on the .NET runtime - what most core banking software in this region is actually built on.

    Costs

    Deep integration with the Microsoft platform, which is leverage or lock-in depending on where you are deploying.

  4. Node.js & Express

    Solves

    One language across the stack, and an event loop suited to the I/O-bound work that most API services actually do.

    Costs

    Single-threaded by default and unopinionated by design. Structure is your responsibility, and nothing will warn you when you lose it.

  5. Laravel

    Solves

    A complete, conventional application framework - queues, scheduling, ORM and auth included - which makes it fast to a correct first version.

    Costs

    The conventions are the value. Fighting them costs more than adopting them.

03What the user actually touches

Where does this render, and who pays for it?

Every rendering decision is a decision about who does the work: the server on every request, the build step once, or the user's device. Get it wrong and you either pay in infrastructure or you pay in someone's battery on a mid-range phone over a slow network - which is what most of the world is using.

  1. Next.js

    Solves

    Per-route control over rendering - static, server-rendered or client - so pages that never change stop costing anything to serve.

    Costs

    The server/client boundary is a real architectural decision. Treating it casually leaks logic and bundle size across it.

  2. React

    Solves

    Composable UI where state changes describe the interface rather than mutating it step by step.

    Costs

    It ships a runtime. Every abstraction on top of it is bytes on the critical path.

  3. Angular

    Solves

    A full framework with dependency injection and structure enforced from the start - valuable on long-lived enterprise applications with many hands on them.

    Costs

    More framework than most products need, and the learning curve is front-loaded.

04Knowing it works

How do you find out before the customer does?

Code that has never been observed in production is a hypothesis. Deployment and observability are not the phase after engineering - they are the part where you learn whether the engineering was correct. A system without instrumentation has not been built yet, it has only been written.

  1. Docker

    Solves

    The same artefact on a laptop, in CI, and in production. Environment drift stops being a category of bug.

    Costs

    An image is not isolation. Layers, base images and build caching are ongoing work, not a one-time setup.

  2. Prometheus

    Solves

    Dimensional time-series metrics pulled from services, with alerting rules expressed against the same query language you debug with.

    Costs

    Cardinality is a real budget. One unbounded label on a high-traffic metric will take down the thing meant to be watching everything else.

  3. Grafana

    Solves

    Turning those metrics into something a human can read at speed while an incident is still open.

    Costs

    Dashboards rot. One that nobody trusts is worse than none, because it is consulted anyway.

  4. Elastic

    Solves

    Full-text search across logs and documents, which is how you answer questions you did not think to make a metric for.

    Costs

    Storage-hungry and cluster-shaped. Index and retention design decides whether the bill is sane.

  5. Nginx

    Solves

    TLS termination, reverse proxying and static serving at the edge, in front of application servers that should not be doing any of it.

    Costs

    Configuration is its own language, and a subtly wrong proxy header is invisible until it is a security finding.

  6. GitHub Actions

    Solves

    Deployment as a repeatable pipeline rather than an SSH session someone remembers the steps for.

    Costs

    Pipelines become infrastructure. Once you depend on them, they need maintenance and review like any other code.

05Principles

None of these are novel. All of them cost something to learn.

  1. 01

    Read the spec twice

    Most production incidents are not clever failures. They are a field that meant something slightly different than assumed, discovered six months later at volume. An hour with the specification is cheaper than a week with the postmortem.

  2. 02

    Make failure a state, not an exception

    Anything crossing a network will fail partway through. If a partial failure leaves a queryable, resumable record, it is an operations task. If it leaves nothing, it is an incident and a customer support ticket.

  3. 03

    Idempotency is not optional

    Every external system will eventually deliver the same event twice. Handlers keyed on the caller's reference converge on one outcome no matter how many times they run. Design for the retry before you need it.

  4. 04

    Boring where it counts

    Novelty belongs in the parts of a system nobody's money depends on. In the settlement path, prefer the technology with the longest, dullest track record.

  5. 05

    Write for the engineer who inherits it

    Code is read far more often than it is written, usually by someone under time pressure who was not in the room for the decision. Leave the reasoning behind, not just the result.

06Shipping

Taken to production and supported afterwards.

C#.NET / ASP.NET CoreTypeScriptJavaScriptNode.jsExpress.jsNext.jsReactMongoDBMS SQLPostgreSQLSocket.IONginxDockerGitHub ActionsAmazon S3
07Working knowledge

Read, operated alongside, or used without claiming depth.

RustSpring BootLaravelAngularKafkagRPCRedisPrometheusGrafanaElasticPythonMySQL