Infra, explained for people who already build things

More than seventy short chapters that give you the vocabulary and mental models engineers use when they talk about servers, networks, pipelines and architecture. Each one takes two or three minutes and links back to things you already run.

Start with the journey below. Every hop a request makes on its way to your app is a chapter, and once you can narrate this path out loud you can follow most infrastructure conversations.

  1. 1
    Someone types a domain

    DNS turns the name into an IP address.

    DNS and record types
  2. 2
    A secure connection opens

    TLS proves the server is who it claims to be and encrypts the traffic.

    HTTPS, TLS and certificates
  3. 3
    The edge answers if it can

    A CDN serves cached copies from a data centre near the visitor.

    CDNs and the edge
  4. 4
    Traffic is spread and routed

    Traffic directors — a load balancer and a reverse proxy — decide which server and which app gets the request.

    Forward and reverse proxies
  5. 5
    Your code runs

    In a container, a VM or a serverless function.

    VMs versus containers
  6. 6
    Data is fetched

    From a cache if possible, otherwise the database.

    Caching and Redis
  7. 7
    Everything is recorded

    Logs, metrics and traces tell you what happened and how fast.

    Logs, metrics and traces

The parts

Your progress is saved in this browser. Mark a chapter as read at the bottom of each page.

A server is just a computer that is always on, waiting for requests.

There's no magic in the word. A server is an ordinary computer, usually sitting in a data centre (a building full of them, with reliable power and very fast internet), that runs with no screen or keyboard attached and never sleeps. When people say "the server", they mean "the computer our code runs on".

Because it has no screen, you control it with text. The terminal (also called the command line or shell) is the window where you type commands like ls (list files) and read the text that comes back. It looks intimidating; it's really just a chat with the computer where every message is an instruction.

SSH (secure shell) is how you open a terminal on a machine that isn't in front of you. You type ssh user@your-server, prove who you are (ideally with an SSH key, a pair of cryptographic files, rather than a password), and from then on everything you type travels to the server encrypted. Nearly all server administration happens over SSH.

Your laptop a terminal window A server always-on computer in a data centre SSH typed commands, encrypted
SSH gives you a terminal on a computer that isn't in front of you.

Most infra confusion is really confusion about which layer someone is talking about.

Engineers split a system into layers, and job titles follow the same lines:

  • Frontend is what runs in the browser: HTML, CSS, JavaScript, your Astro site.
  • Backend is code that runs on a server: APIs, business logic, talking to the database.
  • Infrastructure ("infra") is what the backend runs on: servers, networks, storage, DNS.
  • Platform is the tooling that makes infra easy for other developers to use, such as an internal deploy button. Coolify (a self-hosted tool that gives you a push-to-deploy button on your own server) is a platform product.
  • Operations ("ops") is keeping it all running: monitoring, backups, upgrades, incidents.

"Architecture" sits across all of these. It is the set of decisions about which pieces exist and how they talk to each other, usually drawn as boxes and arrows.

Four nouns you'll hear in almost every infra sentence.

A stack is the set of technologies a product uses. "Our stack is Next.js, Postgres and AWS." People also say "tech stack" or "the stack".

A service is one running piece of software with a job, usually reachable over the network. Your database is a service, Umami (a self-hosted, privacy-friendly alternative to Google Analytics) is a service, an email sender might be a service. A system is a set of services.

An environment is a complete copy of the system for a purpose: dev for building, staging for testing, production (or prod) for real users.

An instance is one running copy of something. Three instances of a service means three copies running side by side. In the cloud, "instance" also just means a virtual server.

An IP address finds the machine; a port finds the program on that machine.

Every device on a network has an IP address. IPv4 looks like 203.0.113.10; IPv6 looks like 2001:db8::1 and exists because the world ran out of IPv4 addresses.

Addresses are either public (reachable from the internet) or private (only inside a network, such as 192.168.x.x at home or 10.x.x.x in a data centre).

A port is a numbered door on a machine. One server can run many programs, each listening on a different port. Common ones: 22 for SSH, 80 for HTTP, 443 for HTTPS, 5432 for Postgres and 6379 for Redis (a database and a cache you'll meet in the databases part), 3000 or 8080 for app servers in development.

Data between machines travels in small chunks called packets, delivered one of two ways: TCP checks that every packet arrives, in order (most of the web uses it), while UDP just sends and hopes, which is faster and fine for things like video calls where a lost split-second doesn't matter.

To "expose" or "open" a port means allowing traffic to reach it. To "bind" a port means a program has claimed it.

DNS is the internet's phone book: it turns names into addresses and other facts.

When you visit a domain, your device asks a resolver (often run by your internet provider, or a public one like Cloudflare's 1.1.1.1). The resolver asks the domain's authoritative nameservers, which hold the real answer. Where you manage those records is called your DNS provider, which may differ from your registrar, the company you bought the domain from.

Records are typed:

TypeWhat it says
AThis name points to an IPv4 address.
AAAASame, for IPv6.
CNAMEThis name is an alias of another name. Can't sit on the bare domain in classic DNS.
MXWhere email for this domain should be delivered.
TXTFree text, used to prove ownership and for email security (SPF, DKIM and DMARC, three standards that prove an email really came from your domain).
NSWhich nameservers are authoritative.
CAAWhich certificate authorities may issue certificates for you.

The bare domain (farhan.app) is called the apex or root. Anything in front of it is a subdomain. Cloudflare's "CNAME flattening" is a workaround for putting an alias on the apex.

dig is a terminal command that asks DNS questions. Try:

dig farhan.app A +short
dig farhan.app MX +short

DNS answers are cached everywhere, and TTL says for how long.

Every record has a TTL (time to live), in seconds. A TTL of 3600 means resolvers may keep reusing the answer for an hour before asking again.

"Waiting for DNS to propagate" really means waiting for old cached answers to expire around the world. Nothing is actively spreading; caches are timing out.

The professional trick before a migration is to lower the TTL a day in advance (say to 60 seconds), make the change, then raise it again once things are stable.

TTL is also a general term: caches, tokens and CDN entries all have TTLs.

HTTP is the language browsers and servers speak; status codes are its one-line verdicts.

A request has a method (GET read, POST create, PUT/PATCH update, DELETE remove), a path, headers (metadata like cookies and content type) and sometimes a body.

Status codes group by first digit:

  • 2xx success: 200 OK, 201 Created, 204 No Content.
  • 3xx go elsewhere: 301 permanent redirect, 302 temporary, 304 not modified (use your cache).
  • 4xx the client did something wrong: 400 bad request, 401 not logged in, 403 logged in but not allowed, 404 not found, 429 too many requests.
  • 5xx the server failed: 500 generic error, 502 bad gateway, 503 unavailable, 504 gateway timeout.

502 and 504 matter for infra: they usually mean a proxy in front of your app couldn't reach it or gave up waiting. The proxy is fine; the thing behind it isn't.

Versions: HTTP/1.1 is the classic, HTTP/2 multiplexes many requests over one connection, HTTP/3 runs over UDP (via QUIC) for faster connections on flaky networks.

TLS encrypts traffic and proves the server's identity; a certificate is the proof.

HTTPS is HTTP wrapped in TLS (the successor to SSL; people still say "SSL cert" out of habit). During the handshake, the server presents a certificate signed by a certificate authority (CA) that browsers trust.

Let's Encrypt is a free CA whose certificates last 90 days, so tools renew them automatically using the ACME protocol. Other terms:

  • Wildcard cert: covers *.farhan.app, all subdomains one level deep.
  • TLS termination: the point where traffic is decrypted, usually at the load balancer or proxy. Behind that point traffic may be plain HTTP inside a private network.
  • End-to-end encryption: encrypted all the way to the app, not just to the edge.
  • mTLS (mutual TLS): both sides present certificates, common between internal services.
  • HSTS: a header telling browsers to only ever use HTTPS for your domain.

A proxy is a middleman. Which side it works for decides its name.

A forward proxy sits in front of clients and makes requests on their behalf. Corporate web filters are forward proxies.

A reverse proxy sits in front of servers. Visitors talk to it, and it forwards each request to the right app behind it. It typically handles:

  • Routing by domain or path (host-based and path-based routing).
  • TLS termination and certificates.
  • Compression, caching, redirects, header rewrites and basic rate limiting.

Common reverse proxies: Nginx, Traefik, Caddy, HAProxy, Envoy. In Kubernetes (the container-orchestration system covered in the containers part) the same job is called an ingress (or the newer Gateway API). The app behind the proxy is called the upstream or origin.

Visitors Reverse proxy reads the hostname Umami mochi.farhan.app Uptime Kuma uptime.farhan.app WordPress cms.farhan.app
One public IP, many apps: the proxy routes by hostname (host-based routing).

A load balancer spreads traffic across several copies of a service so no single one is overwhelmed or critical.

It keeps a pool (or target group) of backends, runs health checks against them, and stops sending traffic to any that fail.

Two families:

  • Layer 4 balancers work on raw TCP/UDP connections. Fast and simple; they don't read the HTTP request.
  • Layer 7 balancers understand HTTP, so they can route by path, header or cookie. A reverse proxy is effectively an L7 balancer.

(The layers come from the OSI model, a seven-level way of describing networking. You only need L4 = transport and L7 = application.)

Distribution methods include round robin, least connections and weighted. Sticky sessions keep a user on the same backend, which is a sign the app is storing state it shouldn't. Draining means letting existing requests finish before removing a server. Cloud providers sell load balancers as products; AWS's are the ALB (layer 7) and NLB (layer 4), names you'll hear a lot.

A CDN keeps copies of your content in data centres close to users.

A content delivery network has hundreds of points of presence (PoPs) worldwide. The first request for a file goes to your origin; the CDN caches the response and serves later requests from the nearest PoP.

  • Cache hit / miss: served from the CDN, or had to go to origin. Hit ratio is the percentage of hits.
  • Purge or invalidate: throw away cached copies so new content appears.
  • Cache-Control headers tell the CDN and browsers how long to keep things.
  • The edge means those PoPs. "Running at the edge" means code executes in the PoP, not in one central region.

CDNs also absorb DDoS attacks (attackers flooding a site with junk traffic to knock it over) and often provide a WAF (web application firewall). Big names: Cloudflare, Fastly, Akamai, AWS CloudFront.

Most of network security is deciding who can reach what, then hiding everything else.

A firewall allows or blocks traffic by rules, usually source, destination and port. Cloud providers call them security groups or network firewall rules. "Default deny" means everything is blocked unless a rule allows it.

Ingress is traffic coming in; egress is traffic going out. (Confusingly, Kubernetes, which you'll meet in the containers part, also uses "ingress" for its reverse proxy.)

NAT (network address translation) lets many private machines share one public IP for outbound traffic. Your home router does this. In the cloud, a NAT gateway lets private servers reach the internet without being reachable from it.

A VPN joins distant machines into one private network. Classic VPNs route through a central server. Mesh VPNs like Tailscale (built on WireGuard) connect devices directly. A bastion host or jump box is the older pattern: one hardened server you SSH into, then hop to private machines.

A VPC is your own private network inside a cloud provider.

A virtual private cloud is an isolated network where you place your servers and databases. You carve it into subnets, smaller address ranges written in CIDR notation like 10.0.1.0/24 (the /24 means the first 24 bits are fixed, giving 256 addresses).

The standard shape:

  • Public subnets hold things that face the internet: load balancers, NAT gateways.
  • Private subnets hold app servers and databases with no direct internet route.
  • Route tables decide where traffic from each subnet goes.

Connecting VPCs together is peering; connecting a VPC to an office is a site-to-site VPN or a dedicated link (AWS Direct Connect, Azure ExpressRoute).

Three ways to rent a computer, from most physical to most abstract.

  • Bare metal or a dedicated server: a whole physical machine that's yours. Predictable performance, slowest to provision.
  • VPS (virtual private server): a slice of a physical machine, carved out by a hypervisor (software that splits one physical machine into several virtual ones). Fixed monthly price, generous bandwidth. Hetzner, DigitalOcean, Linode, OVH.
  • Cloud VM: technically also a VPS, but inside a large platform (AWS EC2, Azure VMs, Google Compute Engine) with APIs, autoscaling, and dozens of managed services beside it. Usually billed per second, with bandwidth charged separately.

Industry shorthand: on-prem (on-premises) means servers in your own building; colo (colocation) means your hardware in someone else's data centre; hybrid cloud mixes on-prem with public cloud; multi-cloud means using more than one provider.

The "as a service" ladder describes how much of the stack someone else manages.

ModelYou manageExamples
IaaSOS, runtime, app, dataEC2, Hetzner Cloud
PaaSApp and data onlyHeroku, Render, Railway, Fly.io, Vercel
FaaS / serverlessIndividual functionsAWS Lambda, Cloudflare Workers
SaaSNothing, you just use itGmail, Xero, Slack

Others you'll hear: DBaaS (managed databases), BaaS (backend as a service, like Supabase or Firebase), CaaS (containers as a service).

A managed service means the provider handles patching, backups and scaling. The trade-off is always cost and control versus effort.

Serverless means you hand over code, not servers, and pay only when it runs.

There are still servers, you just never see them. Key ideas:

  • Functions run in response to events: an HTTP request, a file upload, a schedule, a queue message.
  • Scale to zero: nothing runs (or costs) when idle.
  • Cold start: the delay when a function spins up from nothing. Edge runtimes like Cloudflare Workers have tiny cold starts; traditional Lambda can take hundreds of milliseconds.
  • Stateless: each run starts fresh, so data lives in a database or storage, not in memory.
  • Limits on execution time and memory mean long jobs don't fit well.

Edge functions are serverless functions that run in CDN PoPs, close to users. "Serverless" has also broadened to mean any service with no servers to manage, such as serverless databases (Neon, PlanetScale) that scale and bill by usage.

Where your servers physically sit affects speed, resilience and legal compliance.

  • A region is a geographic area, like eu-west-2 (AWS London) or Hetzner's fsn1 (Falkenstein).
  • An availability zone (AZ) is one or more separate data centres within a region, with independent power and networking. Running across multiple AZs protects you from one building failing.
  • Latency is travel time for a request, measured in milliseconds. London to Frankfurt is about 15ms; London to Sydney about 250ms. Nothing beats the speed of light, so distance matters.
  • Data residency or sovereignty: rules requiring data to stay in a country or region, important under UK GDPR and for public sector contracts.

"Multi-AZ" is the standard minimum for production resilience; "multi-region" is for large companies or strict uptime targets, and is much harder because data has to be synchronised over long distances.

AWS dominates cloud conversations, and its product names are used as shorthand even by people on other clouds.

NameWhat it is
EC2Virtual machines.
S3Object storage for files. "S3-compatible" is an industry standard API.
RDS / AuroraManaged relational databases (Postgres, MySQL).
DynamoDBManaged NoSQL key-value database.
LambdaServerless functions.
ECS / FargateRun containers without managing Kubernetes (the orchestration system in the next part).
EKSManaged Kubernetes.
ECRContainer image registry.
CloudFrontCDN.
Route 53DNS.
ALB / NLBLayer 7 and layer 4 load balancers.
VPCPrivate networking.
IAMUsers, roles and permissions.
SQS / SNSMessage queue / pub-sub notifications.
CloudWatchLogs, metrics and alarms.
Secrets ManagerStores passwords and API keys.
CloudFormation / CDKAWS's infrastructure-as-code tools.

The big three sell the same building blocks under different names.

JobAWSAzureGoogle Cloud
VMsEC2Virtual MachinesCompute Engine
Object storageS3Blob StorageCloud Storage
Managed SQLRDSAzure SQL / Database for PostgreSQLCloud SQL
FunctionsLambdaFunctionsCloud Run functions
Containers, no K8sECS / FargateContainer AppsCloud Run
KubernetesEKSAKSGKE
IdentityIAMEntra ID + RBACCloud IAM
MonitoringCloudWatchAzure MonitorCloud Monitoring
Data warehouseRedshiftSynapse / FabricBigQuery

Azure is strong wherever Microsoft 365 is entrenched (so, most UK corporates and much of the public sector). Google Cloud is known for data and analytics (BigQuery). Cloudflare is increasingly a fourth option for edge compute, storage (R2) and databases (D1).

IAM (identity and access management) controls who can do what to which cloud resources.

  • A principal is anything that can act: a user, a group, or a role.
  • A role is a set of permissions that people or machines assume temporarily, rather than holding permanent keys.
  • A policy is a document listing allowed or denied actions on resources, such as "may read objects in this S3 bucket".
  • A service account is an identity for software, not a human.
  • Access keys are long-lived credentials; modern practice avoids them in favour of short-lived tokens, for example GitHub Actions using OIDC to assume a cloud role without storing any secret.

Large organisations use many accounts (AWS Organizations, Azure subscriptions, GCP projects) to separate prod from dev and contain damage. The root or owner account is locked away and rarely used.

The part of infra where your accounting background is a genuine advantage.

  • On-demand: pay per second or hour, no commitment. The most expensive rate.
  • Reserved instances and savings plans: commit to one or three years for large discounts. Essentially prepayment with a take-or-pay risk.
  • Spot (AWS) or preemptible (GCP): spare capacity at a steep discount that can be taken back at short notice. Good for batch jobs.
  • Egress fees: moving data out of a cloud costs money; moving it in is usually free. This is the classic surprise bill, and a reason people like Cloudflare R2, which charges no egress.
  • Tagging: labelling resources by team or project so costs can be allocated, just like cost centres.
  • FinOps: the discipline of managing cloud spend, with its own job titles. Unit economics such as "cost per customer" or "cost per 1,000 requests" are the language it uses.

Cloud costs are mostly opex; buying servers is capex. That shift is one reason finance teams were involved in cloud migrations from the start.

A VM fakes a whole computer; a container fakes just an isolated process on a shared one.

A virtual machine runs a full operating system on virtual hardware provided by a hypervisor. Strong isolation, but each VM carries a whole OS, so it's heavy and slow to boot.

A container shares the host's operating system kernel (the core of the OS) and isolates only the process, its files and its network. It starts in milliseconds and is small, but isolation is weaker than a VM.

In practice they stack: containers run inside VMs. Your VPS is a VM; Docker runs containers inside it.

Virtual machines Containers App Guest OS (its own) App Guest OS (its own) Hypervisor Physical hardware App App Container runtime (Docker) Host OS on the hardware — one shared kernel
Each VM carries a whole operating system of its own; containers share the host's, which is why they're small and start fast.

Words to know: the host is the machine running containers; the container runtime actually runs them (Docker Engine, containerd, Podman); OCI is the open standard for image formats, so images work across tools.

An image is the recipe's output; a container is that image running.

A Dockerfile lists steps to build an image: start from a base image, copy code, install dependencies, set a start command. Each step creates a cached layer, so unchanged steps don't rebuild.

FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]

Images are stored in a registry: Docker Hub, GitHub Container Registry (GHCR), AWS ECR. An image is named repository:tag, for example umami:postgresql-latest.

  • A tag is a movable label. latest is just a convention and can silently change, so production pins specific versions.
  • A digest (sha256:…) is an unchangeable fingerprint of exact contents.
  • Multi-stage builds compile in one stage and copy only the output into a slim final image.
  • Image scanning checks images for known vulnerabilities.

Containers are disposable, so anything worth keeping lives outside them.

A container's own filesystem is thrown away when it's replaced. To keep data you attach a volume (storage managed by Docker) or a bind mount (a folder from the host). Your nightly rsync backs up volumes precisely because that's where the real data lives.

Containers talk to each other over Docker networks, using service names as hostnames (db:5432) instead of IPs.

Docker Compose describes a multi-container app in one YAML file (a simple, indentation-based configuration format): which images, which ports, which volumes, which environment variables, and what depends on what. It's the standard for running a small stack on one machine.

services:
  app:
    image: ghcr.io/me/app:1.4.2
    environment:
      DATABASE_URL: postgres://app@db:5432/app
    depends_on: [db]
  db:
    image: postgres:16
    volumes: [pgdata:/var/lib/postgresql/data]
volumes:
  pgdata: {}

Compose runs containers on one machine. Orchestration runs them across many, and keeps them running.

Once you have dozens of servers and hundreds of containers, someone has to decide:

  • which machine each container runs on (scheduling);
  • what to do when a container or machine dies (self-healing);
  • how to add copies under load (autoscaling);
  • how to roll out a new version without downtime (rolling updates);
  • how services find each other when they keep moving (service discovery).

An orchestrator does this. You declare the desired state ("three copies of the API, version 1.4") and it constantly works to make reality match. That loop is called reconciliation, and "declarative" is the word for describing what you want rather than the steps to get there.

Kubernetes won this category. Alternatives: HashiCorp Nomad, Docker Swarm (fading), and managed options like AWS ECS or Google Cloud Run that hide the orchestrator entirely.

Kubernetes (K8s) is the most popular orchestrator: it runs your containers across many machines and keeps them running.

It came out of Google, it's open source, and it won so completely that "do we need Kubernetes?" is now a standard engineering debate. It also has its own dictionary, and these words cover most conversations.

TermMeaning
ClusterThe whole system: a control plane plus worker machines.
Control planeThe brain that stores desired state and schedules work.
NodeA worker machine (usually a VM).
PodThe smallest unit: one or more containers that share a network address.
Deployment"Keep N copies of this pod running", with rolling updates.
ReplicaSetWhat a Deployment uses to hold the count. Rarely touched directly.
ServiceA stable internal address that load-balances across matching pods.
Ingress / GatewayRoutes outside HTTP traffic to services. The cluster's reverse proxy.
NamespaceA folder-like boundary to separate teams or environments.
ConfigMap / SecretConfiguration and sensitive values injected into pods.
PersistentVolumeStorage that outlives pods.
StatefulSetLike a Deployment, for things needing stable identity, such as databases.
DaemonSetOne pod on every node, for agents like log collectors.
Job / CronJobRun to completion, once or on a schedule.
HPAHorizontal Pod Autoscaler: adds pods under load.
kubectlThe command-line tool ("cube-control" or "cube-cuttle").
ManifestA YAML file describing a resource.

The tools and patterns that grew up around Kubernetes.

  • Helm: a package manager for Kubernetes. A chart is a templated bundle of manifests; you install it with your own values.
  • Kustomize: an alternative that layers patches on plain YAML instead of templating it.
  • Operator: software that runs inside the cluster and manages a complex app (like a Postgres cluster) the way a human operator would, using custom resources.
  • Sidecar: a helper container in the same pod as your app, handling logging, proxying or secrets so your app doesn't have to.
  • Service mesh (Istio, Linkerd): sidecars or node agents on every service that add mTLS, retries and traffic metrics between services without code changes.
  • k3s, kind, minikube: lightweight Kubernetes for small servers or laptops.
  • Managed K8s: EKS, AKS and GKE run the control plane for you.

The CNCF (Cloud Native Computing Foundation) hosts Kubernetes and many of these tools. "Cloud native" loosely means containers, orchestration, microservices and declarative config.

The words teams use around code changes, beyond commit and push.

  • PR (pull request, GitHub) or MR (merge request, GitLab): a proposal to merge a branch, with discussion and checks.
  • Review, approve, request changes. A reviewer is assigned; CODEOWNERS files auto-assign them by folder.
  • Checks or status checks: automated tests that must pass before merging. "The PR is green" means all passed.
  • Branch protection: rules such as "main needs one approval and passing checks".
  • Merge, squash merge (all commits become one), rebase (replay commits on top of the latest main for a straight history).
  • Merge conflict: two changes touched the same lines.
  • Upstream: the original repo you forked from, or the remote branch you track.
  • Monorepo: many projects in one repository. Polyrepo: one per project.
  • Cherry-pick: copy one specific commit onto another branch, often for a hotfix.

How a team organises branches says a lot about how often it ships.

Trunk-based development: everyone merges small changes into main (the "trunk") at least daily. Unfinished features hide behind feature flags. Used by most fast-moving teams.

GitHub flow: short-lived feature branches off main, a PR each, merge and deploy. A light version of trunk-based.

GitFlow: long-lived develop and main branches plus release and hotfix branches. Suits scheduled releases, like packaged software; seen as heavy for web apps.

Related terms: a feature branch holds one piece of work; a release branch freezes code for a version; a hotfix is an urgent fix straight to production; long-lived branches are a warning sign because they drift and cause painful merges.

CI means every change is automatically built and tested as soon as it's pushed.

The "integration" in CI is integrating your code with everyone else's, frequently, so problems surface early. A CI system runs a pipeline on each push or PR, typically:

  • Install dependencies (with caching to save time).
  • Lint and format check: style and obvious mistakes.
  • Type check, if the language has types.
  • Test: unit tests (small pieces), integration tests (pieces together, such as app plus database), and end-to-end (E2E) tests that drive a real browser.
  • Build: produce the deployable output, called a build artifact.
  • Security scans: dependency vulnerabilities (SCA), code patterns (SAST), leaked secrets.

A flaky test passes and fails randomly and slowly destroys trust in CI. "Breaking the build" means your change made main fail.

CI tools: GitHub Actions, GitLab CI, CircleCI, Jenkins (old but everywhere), Buildkite.

Two different things share the letters CD.

Continuous delivery: every change that passes CI is ready to release, and releasing is a button press.

Continuous deployment: every change that passes CI is released automatically, with no human step.

A deployment pipeline promotes the same build artifact through environments: dev, then staging, then production. Promotion means moving a tested build forward rather than rebuilding it, so what you tested is exactly what ships.

Other terms: release (making a version available, which may differ from deploying it if features are flagged off), deploy freeze (no deploys, often around Christmas or year end), manual approval gate, deployment frequency and lead time (two of the four DORA metrics engineering teams are measured on; the others are change failure rate and time to restore).

GitHub Actions has precise terms. Using the right one is an instant credibility signal.

TermMeaning
WorkflowA YAML file in .github/workflows/. The whole automated process.
Trigger / eventWhat starts it: push, pull_request, schedule (cron), workflow_dispatch (manual button).
RunOne execution of a workflow.
JobA group of steps on one machine. Jobs run in parallel unless linked by needs.
StepA single command or action inside a job.
ActionA reusable step others have published, like actions/checkout.
RunnerThe machine that runs a job. GitHub-hosted, or self-hosted on your own server.
MatrixRun the same job across versions or OSes.
Secrets / variablesEncrypted values and plain config available to workflows.
ArtifactA file a run saves for later jobs or download.
EnvironmentA named target (like production) that can require approvals.
on: { push: { branches: [main] } }
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm test

Same code, different settings, different audiences.

  • Local: your machine.
  • Dev: a shared development environment.
  • Staging (or pre-prod, UAT): as close to production as possible, for final checks. UAT, user acceptance testing, is where business users sign off, a term you'll know from finance system rollouts.
  • Production: real users, real data.
  • Preview or ephemeral environments: a temporary copy spun up for each PR, then destroyed on merge.

What differs between environments is configuration, usually passed in as environment variables (DATABASE_URL, API_KEY). The twelve-factor app principles say config belongs in the environment, never in code. Environment parity means keeping them alike so "works in staging" predicts "works in prod". Config drift is when they quietly diverge.

How you swap old code for new decides how much a bad release can hurt.

  • Recreate: stop old, start new. Simple, with downtime.
  • Rolling: replace instances a few at a time. The default in Kubernetes.
  • Blue-green: run a full new copy (green) beside the old (blue), then switch traffic in one go. Instant rollback by switching back. Costs double capacity briefly.
  • Canary: send a small share of traffic (say 5%) to the new version, watch metrics, then ramp up. Named after canaries in coal mines.
  • Shadow or dark launch: send copied traffic to the new version without users seeing its responses.

Zero-downtime deployment is the goal. A rollback returns to the previous version; a roll-forward fixes the bug with another quick release instead. Database changes complicate rollbacks, which is why migrations are designed to be backwards compatible.

Feature flags separate deploying code from releasing a feature.

A feature flag (or toggle) is an if-statement controlled from outside the code. New code ships switched off, then gets turned on for internal staff, then a percentage of users, then everyone.

  • Progressive rollout: turning a flag on gradually.
  • Targeting: on for certain users, plans or countries.
  • Kill switch: a flag that turns off a misbehaving feature without a deploy.
  • A/B test or experiment: flags used to compare variants on a metric.
  • Flag debt: old flags nobody removed, cluttering the code.

Tools: LaunchDarkly, Unleash, Flagsmith, PostHog, Statsig, or a simple config table.

Instead of clicking around dashboards, describe your infrastructure in files and let a tool create it.

Infrastructure as code (IaC) means servers, networks, DNS and databases are defined in version-controlled files. Benefits: repeatable, reviewable in PRs, and you can rebuild everything from scratch.

  • Terraform (and its open-source fork OpenTofu): the most common IaC tool, works across all clouds. You write resources in HCL, run plan to preview changes, then apply. It records reality in a state file.
  • Pulumi: IaC in real programming languages like TypeScript.
  • CloudFormation, CDK, Bicep: AWS and Azure native tools.
  • Ansible: configuration management, setting up software on existing servers, rather than creating them.

ClickOps is the joking term for managing infra by clicking. Drift is when reality no longer matches the code. GitOps goes further: the Git repo is the source of truth, and an agent (Argo CD, Flux) continuously syncs the live system to match it.

Version numbers are a contract about how risky an upgrade is.

Semantic versioning (semver) uses MAJOR.MINOR.PATCH, such as 2.4.1:

  • Major: breaking changes. Upgrading may require code changes.
  • Minor: new features, backwards compatible.
  • Patch: bug fixes only.

Pre-releases look like 3.0.0-beta.2. LTS (long-term support) versions get fixes for years. EOL (end of life) means no more security patches, which is why Ubuntu 22.04's support window matters.

Dependency terms: a lockfile (package-lock.json) pins exact versions; transitive dependencies are your dependencies' dependencies; Dependabot and Renovate open PRs to update them; a changelog lists what changed; release notes explain it for users. Tags in Git mark the commit each version came from.

Three overlapping job families that all sit between writing code and running it.

DevOps started as a culture: developers and operations share responsibility instead of throwing code over a wall. "You build it, you run it." It's now also a job title, usually meaning someone who owns CI/CD, cloud and IaC.

SRE (site reliability engineering) came from Google: software engineers who treat reliability as an engineering problem, using SLOs, error budgets and automation to reduce toil (repetitive manual work).

Platform engineering builds an internal developer platform (IDP): golden paths, templates and self-service tools so product developers can ship without being infra experts. Backstage is a common portal.

Also heard: DevSecOps (security built into the pipeline), MLOps (the same ideas for machine-learning models), shift left (catch problems earlier in the process, such as security checks in CI rather than after release).

Relational databases are the default; everything else is a specialist tool.

Relational (SQL) databases store data in tables with a fixed schema (an agreed shape for the tables and their columns) and join them with keys. Postgres, MySQL/MariaDB, SQL Server, SQLite. Postgres is the modern favourite.

NoSQL is an umbrella for everything else:

  • Document stores (MongoDB, Firestore): JSON-like records, flexible shape.
  • Key-value stores (Redis, DynamoDB): look up a value by key, extremely fast.
  • Wide-column (Cassandra): huge write volumes.
  • Graph (Neo4j): relationships are the main data.
  • Search engines (Elasticsearch, OpenSearch, Meilisearch): full-text search.
  • Time-series (TimescaleDB, InfluxDB): metrics over time.
  • Vector databases (pgvector, Pinecone): similarity search for AI features.

For analytics there's a split you'll recognise from BI: OLTP databases handle live transactions; OLAP systems (data warehouses like Snowflake, BigQuery) handle big analytical queries. ETL/ELT pipelines move data from one to the other.

Why databases can be trusted with money, and why some queries are slow.

A transaction groups operations so they all succeed or all fail. Like a journal that must balance before it posts. ACID describes the guarantees:

  • Atomicity: all or nothing.
  • Consistency: rules and constraints always hold.
  • Isolation: concurrent transactions don't see each other's half-finished work.
  • Durability: once committed, it survives a crash.

An index is a sorted lookup structure on a column, like an index at the back of a book. It makes reads fast and writes slightly slower. A full table scan reads every row, which is what happens without a useful index. EXPLAIN shows how the database plans to run a query.

Other terms: primary key, foreign key, normalisation (no duplicated data) versus denormalisation (deliberate duplication for speed), deadlock (two transactions waiting on each other), and the N+1 query problem, where code runs one query per item in a list instead of one query for all.

Migrations are version control for your database structure.

A migration is a small script that changes the schema: add a table, add a column, create an index. They're numbered or timestamped, committed to Git, and applied in order. The database records which have run.

Most frameworks include a migration tool (Prisma, Drizzle, Django, Rails, Laravel, Flyway, Liquibase). "Run the migrations" is usually a step in the deploy pipeline.

The hard part is changing a live database without downtime. The standard approach is expand and contract:

  • Expand: add the new column alongside the old one; code writes to both.
  • Backfill: copy existing data into the new column.
  • Switch: code reads from the new column.
  • Contract: remove the old column in a later release.

Each step is safe to roll back. Seeding means loading starting or test data.

How databases survive failures and grow beyond one machine.

Replication copies data from a primary (which accepts writes) to one or more replicas. Older docs say master/slave; modern ones say primary/replica or leader/follower.

  • Read replicas take read traffic off the primary.
  • Synchronous replication waits for the replica to confirm each write (safer, slower). Asynchronous doesn't, so a replica can briefly lag behind. That delay is replication lag.
  • Failover: promoting a replica to primary when the primary dies. Automatic failover is a key feature of managed databases.
  • High availability (HA): set up so a single failure doesn't cause an outage.

When one primary can't handle the writes, you shard or partition: split data across databases by a key such as customer ID. It's powerful and painful, so most teams scale vertically for a very long time first.

Opening a database connection is expensive, so apps reuse a small set of them.

Each connection to Postgres uses memory on the server, and Postgres typically allows only a few hundred. A connection pool keeps a fixed set of open connections and lends them to requests as needed.

Pools live either inside the app (most database libraries have one) or as a separate proxy such as PgBouncer or AWS RDS Proxy.

This matters most with serverless. Hundreds of short-lived function instances each opening their own connection will exhaust the database quickly. That's why serverless database providers offer pooled or HTTP-based connections, and why Cloudflare built Hyperdrive.

Symptoms of pool trouble: "too many connections" errors, or requests hanging while they wait for a free connection (pool exhaustion).

A cache is a fast copy of something slow. The hard part is knowing when it's stale.

Caches exist at every layer: the browser, the CDN, the app's memory, a shared cache server, and the database's own buffers.

Redis is the standard shared cache: an in-memory key-value store that's extremely fast. It's also used for sessions, rate-limit counters, leaderboards and simple queues. Valkey is an open-source fork after a licence change; Memcached is an older, simpler alternative.

  • Cache-aside: check the cache; on a miss, read the database and store the result. The most common pattern.
  • Write-through: update the cache and database together.
  • Invalidation: removing stale entries when data changes. Famously one of the two hard problems in computer science.
  • Eviction: dropping entries when memory is full, often least-recently-used (LRU).
  • Cache stampede: many requests miss at once and all hit the database together.
  • Memoisation: caching a function's result for the same inputs.

Not everything should happen while the user waits.

Sending emails, generating reports, resizing images: slow work goes on a queue. The web request adds a message (the producer) and returns immediately; separate workers (the consumers) pick messages off and process them. This is asynchronous processing.

  • Job queues: BullMQ (on Redis), Sidekiq, Celery, AWS SQS, Cloudflare Queues.
  • Retries with backoff when a job fails, and a dead-letter queue (DLQ) for messages that keep failing.
  • At-least-once delivery: a message may arrive twice, so consumers must be idempotent (see the resilience chapter).
  • Pub/sub (publish/subscribe): one message goes to many subscribers. A topic is the channel.
  • Event streaming (Apache Kafka, AWS Kinesis): an ordered, replayable log of events at huge volume.
  • Cron jobs or scheduled tasks: time-based work.

Three kinds of storage, each suited to different data.

  • Object storage (S3, Cloudflare R2, Backblaze B2, Azure Blob): files stored as objects in buckets, fetched over HTTP by key. Practically unlimited, cheap, durable. Where uploads, images, backups and exports go. Files are called objects or blobs.
  • Block storage (AWS EBS, Hetzner Volumes): a virtual disk attached to one server. Fast, and what databases run on.
  • File storage (AWS EFS, NFS, SMB shares): a shared network drive that several servers mount at once. Your Synology is a file server.

Object storage terms: presigned URLs give time-limited upload or download access without making a bucket public; lifecycle rules move old objects to cheaper storage tiers (like S3 Glacier) or delete them; versioning keeps old copies of overwritten files.

Durability is quoted in nines: S3 claims 99.999999999% ("eleven nines"), meaning data loss is vanishingly unlikely.

A backup plan is defined by two numbers: how much you can lose, and how long you can be down.

  • RPO (recovery point objective): maximum acceptable data loss, in time. Nightly backups mean an RPO of up to 24 hours.
  • RTO (recovery time objective): maximum acceptable time to be back up.

Techniques: snapshots (point-in-time disk copies), logical dumps (pg_dump), and point-in-time recovery (PITR), which replays the database's write-ahead log to restore to any second.

The 3-2-1 rule: three copies, on two kinds of media, one off-site. Immutable backups can't be changed or deleted for a set period, protecting against ransomware. Disaster recovery (DR) is the wider plan for losing a whole site.

The rule everyone repeats: a backup you haven't restored isn't a backup. Scheduled restore tests are the proof.

AuthN asks who you are; AuthZ asks what you're allowed to do.

Authentication (authN) verifies identity: passwords, magic links, passkeys, SSO. Adding a second factor is MFA or 2FA: something you know plus something you have, such as a TOTP code from an authenticator app.

Authorisation (authZ) decides permissions once identity is known. Models:

  • RBAC (role-based): permissions attach to roles like admin, editor, viewer.
  • ABAC (attribute-based): rules use attributes, such as "managers can approve expenses under £5,000 in their own cost centre".
  • ReBAC (relationship-based): permissions follow relationships, like Google Docs sharing.

Passkeys (built on WebAuthn) replace passwords with device-held cryptographic keys and are becoming the default. Multi-tenancy means one system serves many customers (tenants) whose data must never mix. It's the central authZ risk in any SaaS.

After login, the server needs a way to recognise you on every request.

Session-based auth: the server stores a session and gives the browser a random session ID in a cookie. Easy to revoke: delete the session.

Token-based auth: the server gives the client a signed token that it sends in the Authorization: Bearer … header. Common for APIs and mobile apps.

A JWT (JSON Web Token, said "jot") is a popular token format: a small JSON payload (claims, such as user ID and expiry) plus a signature. Anyone can read it; only the issuer can create a valid one. Because the server doesn't store it, it's hard to revoke, so JWTs are kept short-lived and paired with a longer-lived refresh token.

Cookie flags to know: HttpOnly (JavaScript can't read it), Secure (HTTPS only), SameSite (limits cross-site sending, which blocks CSRF).

OAuth lets one app access another on your behalf; OIDC adds "and here's who logged in".

OAuth 2.0 is about delegated access. When an app asks to "read your Google Calendar", you log in at Google, approve specific scopes, and Google gives the app an access token. The app never sees your password. Roles: the resource owner (you), the client (the app), the authorisation server (Google), the resource server (the Calendar API).

OpenID Connect (OIDC) sits on top of OAuth and adds an ID token describing who the user is. "Sign in with Google" is OIDC.

SSO (single sign-on) means one login across many apps. Enterprises run an identity provider (IdP) such as Microsoft Entra ID, Okta or Google Workspace. Older enterprise SSO uses SAML (XML-based); newer uses OIDC. SCIM automatically creates and removes user accounts in apps when HR adds or removes staff.

Auth platforms like Auth0, Clerk, WorkOS and Supabase Auth handle all this so you don't build it yourself.

A secret is any value that grants access: API keys, passwords, tokens, private keys.

The rules:

  • Never commit secrets to Git, even in private repos. Git history keeps them forever.
  • Inject them at runtime as environment variables or mounted files.
  • Store them in a secrets manager: HashiCorp Vault, AWS Secrets Manager, Doppler, Infisical, 1Password, or your CI or platform's encrypted secrets store.
  • Rotate them regularly, and immediately after any leak.
  • Scope each one to the least access it needs.

.env files are fine locally but belong in .gitignore. Secret scanning (GitHub has it built in) catches leaks in commits. A leaked credential should be treated as compromised the moment it's public, since bots scan GitHub within minutes.

Assume something will be breached, and limit what it can reach.

  • Least privilege: every person and service gets the minimum access needed.
  • Blast radius: how much damage one compromised part can do. Least privilege shrinks it.
  • Defence in depth: several independent layers, so one failure isn't fatal.
  • Zero trust: being inside the network grants nothing; every request is authenticated and authorised. Tools like Tailscale, Cloudflare Access and Google BeyondCorp implement it.
  • Attack surface: everything an attacker could reach. Closing ports and removing unused services reduces it.
  • Hardening: locking a server down, such as disabling password SSH, running services as non-root users, and applying updates promptly.
  • Patch management and CVEs: public IDs for known vulnerabilities (like CVE-2024-3094), rated by CVSS score.

The shorthand security people use, in one place.

NameWhat happensMain defence
SQL injectionUser input is run as database code.Parameterised queries.
XSSAttacker's script runs in other users' browsers.Escape output, Content Security Policy.
CSRFA malicious site triggers actions using your logged-in cookies.SameSite cookies, CSRF tokens.
SSRFThe server is tricked into fetching internal URLs.Allow-lists for outbound requests.
IDORChanging an ID in a URL shows someone else's data.Check ownership on every request.
DDoSFlooding a service with traffic.CDN or WAF, rate limiting.
Credential stuffingLeaked passwords tried on your login.MFA, rate limits, breach checks.
Supply chain attackA compromised dependency or build tool.Lockfiles, pinned versions, SBOMs.
PhishingTricking people into giving credentials.Passkeys, training.

The OWASP Top 10 is the standard list of web app risks. An SBOM (software bill of materials) is an inventory of every component in your software.

The browser security rule that front-end developers meet most often, and the header that relaxes it.

An origin is scheme plus domain plus port: https://farhan.app and https://api.farhan.app are different origins. The same-origin policy stops JavaScript on one origin from reading responses from another.

CORS (cross-origin resource sharing) lets a server opt in: it sends headers like Access-Control-Allow-Origin: https://farhan.app to say which origins may read its responses. For some requests the browser first sends an OPTIONS preflight to ask permission.

Key facts:

  • CORS is enforced by browsers only. curl and servers ignore it, so it isn't an API security measure.
  • A CORS error is fixed on the server being called, not in your front-end code.
  • Allow-Origin: * can't be combined with cookies or credentials.

Security frameworks are audits of controls, a world you already know from finance.

  • SOC 2: a US-origin audit report on controls around security, availability and confidentiality. Type I checks controls are designed properly at one date; Type II checks they operated over a period (usually 6 to 12 months). B2B customers routinely ask for it.
  • ISO 27001: the international standard for an information security management system, more common in the UK and Europe. Certification rather than an attestation report.
  • Cyber Essentials: the UK government-backed baseline scheme, often required for public sector suppliers like TfL.
  • UK GDPR: data protection law. Terms include data controller, data processor, DPA (data processing agreement), DPIA (impact assessment) and subject access requests.
  • PCI DSS: rules for handling card data. Most companies avoid it by letting Stripe or similar hold the card.

A penetration test (pen test) is paid ethical hacking. A vulnerability disclosure policy or bug bounty invites outsiders to report issues.

The three kinds of evidence engineers use to understand a running system.

  • Logs: timestamped records of events. "User 42 logged in." Best as structured logs (JSON with fields) so they can be searched and filtered. Levels: debug, info, warn, error.
  • Metrics: numbers over time. Requests per second, CPU usage, error rate. Cheap to store, ideal for dashboards and alerts. Watch out for cardinality: a metric split by user ID creates millions of series.
  • Traces: the path of a single request through many services, broken into timed spans. They show where time went, for example 800ms of a 900ms request spent in one database call.

Observability is the ability to answer new questions about your system from this data, without shipping new code. Monitoring checks known problems; observability helps with unknown ones.

OpenTelemetry (OTel) is the open standard for collecting all three. Tools: Grafana with Prometheus, Loki and Tempo; Datadog; New Relic; Honeycomb; Sentry for errors; Better Stack.

Dashboards are for looking; alerts are for being told.

Two classic checklists for what to watch:

  • The four golden signals (from Google SRE): latency, traffic, errors, saturation.
  • RED for services: rate, errors, duration. USE for resources: utilisation, saturation, errors.

Latency percentiles: p50 is the median; p95 and p99 mean 95% or 99% of requests were faster. Averages hide the slow tail that users actually feel, so engineers talk in percentiles.

Alerting terms: a threshold triggers an alert; paging means waking someone up (via PagerDuty, Opsgenie or incident.io); alert fatigue sets in when too many alerts fire and people start ignoring them. Good practice is to alert on symptoms users feel (errors, slowness), not every cause (high CPU).

Synthetic monitoring runs scripted checks from outside, like a fake user logging in every five minutes. RUM (real user monitoring) measures what actual visitors experience, including Core Web Vitals.

Small endpoints and pings that let machines judge whether a service is alive.

A health check is an endpoint like /health or /healthz that returns 200 when the service is fine. Load balancers and orchestrators call it constantly.

Kubernetes separates the questions:

  • Liveness: is the process stuck? If not live, restart it.
  • Readiness: can it take traffic right now? If not ready, stop sending requests but don't restart.
  • Startup: has it finished booting?

A shallow check just confirms the process responds. A deep check also tests dependencies like the database, which is more informative but can cause a whole fleet to be marked unhealthy when one shared dependency blips.

Push monitoring reverses the direction: the service sends a heartbeat on schedule, and silence triggers the alert. It suits things you can't reach from outside, like cron jobs. This pattern is sometimes called a dead man's switch.

Three nested ideas for putting a number on reliability.

  • SLI (indicator): what you measure. "Percentage of requests that succeed in under 300ms."
  • SLO (objective): the internal target. "99.9% over 30 days."
  • SLA (agreement): the contractual promise to customers, with service credits if missed. Always looser than the SLO so you have a margin.

Availability in "nines":

TargetAllowed downtime per 30 days
99% (two nines)about 7.2 hours
99.9% (three nines)about 43 minutes
99.99% (four nines)about 4.3 minutes
99.999% (five nines)about 26 seconds

The gap between 100% and the SLO is the error budget. While budget remains, teams ship quickly; when it's spent, they slow down and fix reliability. It turns an argument into a number. Burn rate is how fast the budget is being used.

How teams respond when something breaks, and learn from it afterwards.

  • On-call: a rota of engineers reachable out of hours. A rotation or schedule assigns primary and secondary.
  • Incident: an unplanned disruption. Graded by severity: SEV1 or P1 is critical (major outage), down to SEV4 for minor issues.
  • Incident commander: coordinates the response; others investigate. A status page updates customers.
  • Mitigate first (stop the bleeding, often by rolling back), then find the root cause.
  • MTTD, MTTA, MTTR: mean time to detect, acknowledge, and resolve or recover.
  • Runbook or playbook: step-by-step instructions for known problems.
  • Postmortem (or incident review, retrospective): a written account of what happened, why, and follow-up action items. Blameless postmortems focus on systems, not individuals.

Chaos engineering deliberately breaks things in controlled ways to check resilience. Game days are rehearsed incidents.

The biggest architecture debate, which is really about team size.

A monolith is one application deployed as a single unit. Simple to build, test and deploy. Most successful products start this way. A modular monolith keeps one deployment but enforces clean internal boundaries.

Microservices split the system into many small services, each owning its data and deployed independently, talking over the network. Benefits: teams work and deploy independently, services scale separately. Costs: network failures, distributed debugging, data consistency, much more infrastructure.

Related terms:

  • Distributed monolith: microservices so tangled they must deploy together. The worst of both.
  • Service boundaries and bounded contexts (from domain-driven design, DDD): where to cut.
  • Conway's law: systems end up mirroring the communication structure of the organisation that builds them.
  • Strangler fig: replacing an old system gradually by routing features to new code one piece at a time.

Two ways to handle more load, and the property that makes the second one possible.

Vertical scaling (scaling up): a bigger machine. More CPU, more RAM. Simple, no code changes, but has a ceiling and a single point of failure.

Horizontal scaling (scaling out): more machines behind a load balancer. No real ceiling and more resilient, but the app must be stateless.

Stateless means any instance can handle any request, because nothing important lives in one instance's memory or disk. Sessions go to Redis or a database, uploads to object storage. Stateful components (databases, caches) are scaled differently and more carefully.

Autoscaling adds and removes instances automatically based on metrics such as CPU or queue length. Elasticity is the ability to grow and shrink with demand. Bottleneck: whichever component limits the whole system, often the database.

The main styles services use to talk to each other.

REST: resources at URLs, acted on with HTTP methods. GET /posts/12, POST /posts. The default for public APIs. Usually JSON. Documented with an OpenAPI (formerly Swagger) specification.

GraphQL: one endpoint where the client sends a query describing exactly which fields it wants. Avoids over-fetching and many round trips; adds complexity and caching challenges. WordPress has it via WPGraphQL.

gRPC: fast binary protocol using Protocol Buffers, popular between internal microservices.

tRPC: type-safe calls between a TypeScript front end and back end, no schema file needed.

API design terms: endpoint, payload, pagination (offset-based versus cursor-based), versioning (/v1/), breaking change, API gateway (a front door handling auth, rate limits and routing for many APIs), SDK (a client library wrapping an API), and contract (the agreed shape of requests and responses).

Three ways to find out that something changed somewhere else.

  • Polling: ask repeatedly, "anything new?" Simple, wasteful, slow to notice. Long polling holds the request open until there's news.
  • Webhooks: the other system calls your URL when something happens. Stripe calling your server on payment is the textbook case. Receivers should verify a signature, respond quickly, and handle duplicates.
  • WebSockets: a persistent two-way connection for real-time features like chat or live dashboards.
  • Server-sent events (SSE): one-way streaming from server to browser. How AI chat responses usually stream in.

Webhooks are sometimes called "reverse APIs" or "HTTP callbacks". A deploy hook is simply a webhook that triggers a build.

The defensive habits that stop one slow or failing service from taking everything down.

  • Timeouts: never wait forever for another service. Without them, requests pile up and exhaust resources.
  • Retries with exponential backoff and jitter: try again after 1s, 2s, 4s, with some randomness so clients don't all retry at the same instant (a thundering herd).
  • Idempotency: doing an operation twice has the same effect as once. Essential when retrying anything that changes data. APIs accept an idempotency key so a retried payment isn't charged twice.
  • Rate limiting: capping requests per user or IP per time window, returning HTTP 429. Algorithms: token bucket, sliding window. Throttling slows rather than rejects.
  • Circuit breaker: after repeated failures, stop calling a service for a while and fail fast instead.
  • Graceful degradation: when a dependency fails, offer a reduced experience rather than an error page.
  • Backpressure: signalling upstream to slow down when you're overwhelmed.

Reliability comes from having spares, and knowing which parts don't have one.

  • Single point of failure (SPOF): one component whose failure takes the whole system down.
  • Redundancy: duplicate components so one can fail. N+1 means one more than you need.
  • Active-active: all copies serve traffic. Active-passive: a standby waits to take over.
  • Fault tolerance: continuing to work through failures. Fault isolation: containing a failure to one area (also called bulkheads, after ship compartments).
  • Cascading failure: one overloaded part pushes load onto others until they all fall over.
  • Dependencies: your uptime can't exceed that of the services you rely on. If two services you depend on are each 99.9%, your ceiling is about 99.8%.

Once data lives in more than one place, you choose between always-correct and always-available.

Strong consistency: every read sees the latest write. Eventual consistency: copies may briefly disagree but will converge. DNS, CDN caches and read replicas are all eventually consistent.

The CAP theorem says that during a network partition (some machines can't reach others), a distributed system must choose between consistency (refuse requests it can't answer correctly) and availability (answer anyway, possibly with stale data). Banks lean to consistency; social feeds lean to availability.

Other terms: read-your-writes (at least you see your own changes immediately), race condition (outcome depends on timing), optimistic locking (detect conflicting edits with a version number), distributed transaction and the saga pattern (a chain of steps with compensating actions if one fails, since a single database transaction can't span services).

Instead of services calling each other, they announce what happened and let others react.

In a request-driven system, the order service calls the email service, the inventory service and the analytics service directly. In an event-driven system, the order service publishes an event ("OrderPlaced") and each interested service subscribes. The publisher doesn't know or care who's listening.

This decouples services: new features can react to existing events without changing the original code. The cost is that flows become harder to follow and debug.

  • Event bus or broker: the infrastructure carrying events (Kafka, RabbitMQ, AWS EventBridge).
  • Event sourcing: storing every change as an event and deriving current state from the full history. Closely resembles a general ledger rebuilt from journals.
  • CQRS: separate models for writing and reading data.
  • Outbox pattern: save the event in the same database transaction as the data change, then publish it, so neither is lost.
  • Choreography (services react independently) versus orchestration (a coordinator directs each step).

How engineering work is planned and tracked.

  • Agile: working in short cycles with frequent feedback, rather than one big plan (waterfall).
  • Scrum: an Agile framework with fixed sprints (usually two weeks), sprint planning, a daily stand-up, a sprint review and a retro (retrospective).
  • Kanban: continuous flow across a board (to do, in progress, done), with WIP limits on work in progress.
  • Backlog: the prioritised list of work. Grooming or refinement keeps it tidy.
  • Ticket, issue or story: one unit of work, often in Jira or Linear. An epic groups related stories.
  • Story points: relative effort estimates. Velocity: points completed per sprint.
  • Acceptance criteria and definition of done: when a ticket counts as finished.
  • Spike: a time-boxed investigation to reduce uncertainty.
  • MVP: minimum viable product. PoC: proof of concept.

How engineering teams decide things in writing.

  • Design doc or tech spec: describes a proposed system before it's built, covering goals, non-goals, options considered and the chosen approach.
  • RFC (request for comments): a design doc circulated for feedback. Borrowed from the documents that define internet standards.
  • ADR (architecture decision record): a short, permanent note of one decision, its context and consequences. Stored in the repo so future engineers know why.
  • PRD (product requirements document): the product side's "what and why", which engineering responds to with a design doc.
  • Trade-off: the word that should appear in every one of these documents.
  • Non-functional requirements (NFRs): performance, security, availability, cost. The "-ilities": scalability, maintainability, observability.

The informal words you'll hear in Slack and meetings.

TermMeaning
LGTM"Looks good to me." An approval.
NitA minor, optional review comment.
Ship / ship itRelease.
ProdProduction.
HotfixAn urgent fix straight to production.
Tech debtShortcuts that make future work slower. Taken on deliberately or not.
Greenfield / brownfieldStarting fresh versus working within existing systems.
LegacyOld code still in use, often with no tests or original authors.
BikesheddingArguing about trivial details while ignoring hard ones.
Yak shavingA chain of side tasks needed before the real task.
FootgunA feature that makes it easy to hurt yourself.
DogfoodingUsing your own product internally.
Happy path / edge caseThe normal flow versus unusual inputs.
BoilerplateRepetitive setup code.
Rubber duckingExplaining a problem out loud to find the answer.
Works on my machineEnvironment-specific bug, usually config or versions.
Blast radiusHow much a failure or change could affect.
ToilManual, repetitive operational work.
Bus factorHow many people could leave before a project stalls.
Vendor lock-inBeing hard to move away from a provider.
Build vs buyMake it yourself or pay for a product.
HeisenbugA bug that disappears when you try to observe it.

Pairs that sound similar but mean different things. Getting these right is where credibility shows.

Often confusedThe difference
Workflow vs integrationA GitHub workflow is automation in your repo. An integration is a connected external service.
Deploy vs releaseDeploying puts code on servers; releasing makes a feature available to users.
Continuous delivery vs deploymentReady to release on demand versus released automatically.
Authentication vs authorisationWho you are versus what you may do.
Latency vs throughputHow long one request takes versus how many are handled per second.
Availability vs durabilityCan I use it now, versus is my data safe long term.
Backup vs replicaA replica copies mistakes instantly; only a backup lets you go back in time.
Container vs imageA running instance versus the packaged template.
Ingress (networking) vs Ingress (Kubernetes)Inbound traffic in general versus the K8s routing resource.
Proxy vs load balancerOverlapping; a load balancer's defining job is spreading traffic across copies.
Encryption vs hashingEncryption is reversible with a key; hashing is one-way (how passwords are stored).
Library vs frameworkYou call a library; a framework calls your code.
Registrar vs DNS hostWhere the domain is bought versus where its records are served.
Uptime vs SLOA measurement versus a target for it.

Putting it together: the same system, said three ways.

Engineers describe systems from the outside in, naming each hop and its responsibility. Here's your own setup at three levels of detail.

The one-liner:

The thirty-second version:

The ops answer, if someone asks about resilience:

Notice the pattern: what it is, where it runs, how traffic reaches it, what happens when it fails, and what you'd improve. That structure works for any system.

Quick definitions. Filter to jump to a term.

ACME
Protocol used to request and renew TLS certificates automatically.
API gateway
Front door for APIs that handles routing, auth and rate limits.
Artifact
A file produced by a build, ready to deploy or download.
Autoscaling
Adding or removing instances automatically based on load.
Availability zone
An isolated data centre group within a cloud region.
Backoff
Waiting progressively longer between retries.
Bastion host
A hardened server used as the gateway into a private network.
Blue-green
Deploy strategy running old and new side by side, then switching traffic.
Canary
Releasing to a small share of traffic first.
CDN
Network of edge servers caching content near users.
CIDR
Notation for IP address ranges, like 10.0.0.0/16.
Circuit breaker
Stops calling a failing dependency for a while.
Cold start
Delay when a serverless function starts from nothing.
Container
An isolated process sharing the host's kernel.
Control plane / data plane
The part that manages configuration versus the part that carries real traffic.
Cron
Time-based job scheduler, and its schedule syntax.
Daemon
A background process on a server, often ending in d (sshd, dockerd).
DDoS
Attack that floods a service with junk traffic to knock it offline.
Docker
The most common tool for building and running containers.
Drift
Live systems no longer matching their definition in code.
Egress
Outbound traffic, and the fees clouds charge for it.
Ephemeral
Short-lived and disposable, such as preview environments or container disks.
Failover
Switching to a standby when the primary fails.
Fan-out
One event triggering many parallel tasks.
Hypervisor
Software that runs virtual machines.
Idempotent
Safe to repeat; the result is the same.
Immutable infrastructure
Replacing servers rather than modifying them in place.
Ingress
Inbound traffic; in Kubernetes, the HTTP routing resource.
Kernel
The core of an operating system, shared by containers on a host.
Kubernetes
The most popular orchestrator: runs containers across many machines and keeps them running.
Latency
Time for one request to complete.
Load balancer
Distributes traffic across several backends.
Mesh VPN
A VPN where devices connect directly to each other, like Tailscale.
Middleware
Code that runs between receiving a request and handling it, such as auth checks.
Multi-tenant
One system serving many customers with separated data.
Namespace
An isolating boundary for names or resources.
Observability
Understanding a system's internals from its outputs.
Origin
The source server behind a CDN; in browsers, scheme plus host plus port.
p99
The latency 99% of requests beat.
Payload
The data carried in a request or message body.
PoP
Point of presence, a CDN edge location.
Postgres
The most popular open-source relational (SQL) database.
Provisioning
Creating and setting up infrastructure.
Reconciliation
Continuously making actual state match desired state.
Redis
In-memory key-value store used for caching, sessions and queues.
Registry
Storage for container images.
Replica
A copy of a service or database.
Reverse proxy
Server that receives traffic and forwards it to apps behind it.
Runbook
Step-by-step guide for an operational task or incident.
Runner
Machine that executes CI jobs.
Runtime
The environment code executes in, such as Node.js, or a container runtime.
Sharding
Splitting data across several databases by key.
Sidecar
Helper container running beside the main app container.
SLO
Internal reliability target.
SSH
Secure shell: opens an encrypted terminal on a remote machine.
Stateless
Keeps no data between requests in the instance itself.
TCP
Delivery method that checks every packet arrives, in order. Most of the web uses it.
Throughput
Amount of work handled per unit of time.
TLS termination
The point where encrypted traffic is decrypted.
Traefik
A reverse proxy that configures itself from container labels; what Coolify uses.
UDP
Fast delivery method with no guarantees, used where speed beats completeness.
Upstream / downstream
The services you depend on versus those that depend on you.
VPC
Private network inside a cloud provider.
WAF
Web application firewall that filters malicious HTTP requests.
Webhook
An HTTP call made to your URL when an event happens elsewhere.
YAML
Indentation-based config format used by Compose, Kubernetes and CI.