cswork / libraryOpen practice workspace

Interview guides · ALTEN Belgium

ALTEN Belgium Software Engineer Interview Guide

ALTEN Belgium Software Engineer interview guide: reported questions on OOP, debugging, threads, Git branching and REST vs SOAP, plus a 7-day plan.

The 60-second brief

Candidates describe ALTEN Belgium as a technical consultancy. Its software engineers work on client projects in sectors such as automotive, aerospace, telecommunications and energy, sometimes at the client's site and sometimes in ALTEN's own technical centers. The work reported for the role spans embedded systems, cloud-native applications and enterprise software, so the stack depends on the project. Accounts of the role mention stand-ups, code reviews and documentation work, along with reporting to an ALTEN manager while working with the client's technical leads.

This guide is for a Software Engineer candidate interviewing with ALTEN Belgium. It covers the five reported technical and behavioral questions, the evaluation areas candidates describe (data structures and algorithms, design patterns, system architecture, trade-off analysis), the consultancy angle of the process, and a seven-day plan. It does not cover pay, and it makes no claim about a fixed round order, because none has been reported.

No named rounds have been reported. Candidates describe a path from an HR screening to technical and managerial reviews, with coding challenges that range from online assessments to live technical discussions, and a timeline that depends on the client project.

Focus areas

  • Backend Development
  • Frontend Development
  • React

Overview

The reported questions are fundamentals, not puzzles: object-oriented programming with a practical example, debugging a complex production issue, the difference between a process and a thread, version control and branching strategies, and REST versus SOAP. Each one rewards a short, structured answer built on something you have actually done. Reciting definitions is the weakest way to answer any of them.

Candidates also report evaluation areas that go a little beyond those five: arrays, linked lists and basic sorting and searching, design patterns such as Singleton, Factory and Observer, and how components interact in a microservice or embedded system. Topic tags attached to this role include backend development, frontend development, React, transaction management and the Spring Framework. The listed requirements name Java, C++ or Python as core languages, with cloud platforms (AWS or Azure), Docker, Kubernetes and Agile or Scrum as extras. Pick the language you can write fastest and prepare every example in it.

Because the role is client-facing consulting, candidates report that the process also looks at flexibility about location, how quickly you adapt to a new team or project architecture, and how clearly you communicate. Prepare to walk through any line on your CV, to explain a past decision as a trade-off such as performance against maintainability, and to say which client sector, if any, you already know. Ask the recruiter which project or client the interview is for, since the technical emphasis shifts with it.

Where to focus your preparation

No round names or order have been reported for ALTEN Belgium, so this guide treats the loop as one preparation block built from the reported questions and evaluation areas.

Preparation focus

Candidates do not report a fixed list of rounds. They describe a progression from an HR screening to technical and managerial reviews, and say the timeline depends on the availability of a specific client project. Coding challenges are reported in varying forms, from online assessments to live technical discussions. Because the format varies, ask the recruiter what the stages are and whether you will write code, then prepare in three layers. Start with your personal narrative and CV, where every project bullet should come with the decision you made and its trade-off. Move to the technical fundamentals behind the five reported questions plus arrays, linked lists, sorting, searching, the common design patterns, Spring transactions and React basics. Finish with the consultant questions about location, adapting to a client's way of working and communicating with both ALTEN managers and client leads.

What to demonstrate

  • Command of fundamentals in your main language: OOP, threads and processes, API styles, version control
  • Ability to explain a past project and the trade-offs behind it
  • Working code for basic data structure and algorithm tasks if a coding challenge is part of your loop
  • Communication and adaptability for client-facing work

How to prepare

  • Ask the recruiter which project or client the role is for, which stages to expect and whether a coding test is included
  • Write one short spoken answer, with an example, for each of the five reported questions, and for every CV bullet note the decision you made, the alternative you rejected and the result
  • Solve reverse-a-linked-list, binary search and merge sort in your main language without looking anything up, and state the complexity of each
  • Since frontend development and React appear among the tested topics, review React state versus props, useEffect dependencies and cleanup, keys in lists, and calling a Spring REST endpoint from a component with loading, error and CORS handling

Where candidates lose points

Defining encapsulation, inheritance, polymorphism and abstraction as textbook lines with no example

Prepare one small example in your main language that shows all four, such as an abstract base class holding shared logic with two subclasses behind a single call site, and say what each pillar bought you in that code.

Answering the production debugging question with a guess at a fix

Give a sequence: establish impact and scope, check what changed recently, read logs and metrics, reproduce in a safe environment, form one hypothesis at a time, choose between rollback and fix, then follow up with a postmortem and a test that would have caught it.

Treating process versus thread as a vocabulary question and giving no use case

State the concrete difference (separate address spaces versus shared memory in one process), the cost of each (creation, context switching, communication), the risk of threads (races, deadlocks, locks) and one scenario where you would pick each. If you use Python, mention how the global interpreter lock affects the choice for CPU-bound work.

Reducing REST versus SOAP to "REST is lighter"

Compare them on specifics: REST is an architectural style over HTTP resources and verbs, usually with JSON and cacheable, stateless calls; SOAP is a protocol with XML envelopes, a WSDL contract and standardized extensions such as WS-Security. Say when a formal contract matters and when a simple resource API does.

Showing technical skill but not the consultant side

Prepare direct answers on working at a client site, moving between projects, learning an unfamiliar domain quickly and reporting to two parties. Back each answer with a real example, and be ready to explain every line of your CV with the decision behind it.

Questions & practice

Can you explain the difference between a process and a thread, and when would you use one over the other?

Medium · Technical and Domain Knowledge

Approach

  1. Define both precisely: a process has its own virtual address space and owns resources such as file descriptors or handles; threads are units of execution inside a process that share its heap, globals and open files, while each thread has its own stack, registers, program counter and thread-local storage.
  2. Compare the costs: creating a thread and switching between threads of the same process is cheaper than doing so for processes because the address space stays the same. Processes communicate through IPC (pipes, sockets, shared memory, message queues); threads communicate through shared memory and therefore need synchronisation (mutexes, atomics, concurrent collections).
  3. Compare failure isolation: a segmentation fault or unhandled fatal error in one thread can take down the whole process, while a crashed child process leaves its parent and siblings running. That isolation is the main reason to choose processes for untrusted or crash-prone work.
  4. Give language-specific rules. In CPython the GIL lets only one thread run Python bytecode at a time, so CPU-bound work uses multiprocessing and I/O-bound work uses threads or asyncio. In Java, threads run in parallel on multiple cores; use an ExecutorService thread pool rather than raw threads, and virtual threads (Java 21) for large numbers of blocking I/O tasks. In C or C++, choose between pthreads/std::thread and fork() depending on the isolation you need.
  5. Name the hazards that come with shared memory: race conditions on read-modify-write (count++ is not atomic), deadlock from inconsistent lock order, and visibility issues without proper memory barriers (volatile or synchronized in Java).

Follow-up

  • What are the four conditions for a deadlock, and which one would you break in practice?
  • How does fork() avoid copying the parent's whole memory, and what is copy-on-write?
  • How would you size a thread pool for CPU-bound work compared with I/O-bound work?

Find overlapping job attempts and peak concurrency from lease records

Medium · sweep line · intervals · leases

A day of job_run history yields about 50,000,000 attempt records: (job_run_id, job_type, attempt, started_at, finished_at which is NULL when the worker died, lease_expires_at). Leases expire on a clock, so a job that outran its lease ran twice. Produce (a) every job_run_id whose attempts overlapped in wall-clock time and (b) the peak number of simultaneously running attempts per job_type with the minute it occurred. Target O(n log n). State how you treat a NULL finished_at and what clock skew does to your answer.

Approach

  1. Define the interval before sorting anything: an attempt occupies [started_at, COALESCE(finished_at, lease_expires_at)). finished_at is observed and lease_expires_at is only a promise, so every attempt without a finish contributes an estimate and the whole result is a lower bound on overlap rather than an exact count.
  2. For peak concurrency, sweep: emit 2n endpoints, sort by (timestamp, kind) with ends ordered before starts at equal timestamps, then walk the sequence maintaining a counter per job_type and record each type's maximum with its timestamp. O(n log n) dominated by the sort, O(n) space, or O(1) extra if the sort is external and the walk streams.
  3. For overlap detection, do not compare attempts pairwise. A single global sort by (job_run_id, started_at) gives both the grouping and the order; within a group, keep the maximum end seen so far and report an overlap exactly when the next start is less than that running maximum, which is one linear pass after the sort.
  4. Half-open intervals matter and are easy to get wrong: with closed intervals an attempt ending at the same millisecond another begins reads as concurrency two, and across 50,000,000 records that artefact swamps the real signal.

Follow-up

  • A handler is not idempotent and you have found 400 overlapping jobs. Which of them actually caused damage, and what would you query to find out?
  • Peak concurrency for one job_type is 4 against a configured cap of 4. Is the cap working, or is the data hiding attempts that never started?

Collapse a redelivered event batch into per-aggregate high-water marks

Easy · hashing · at-least-once · aggregation

You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.

Approach

  1. One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
  2. Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
  3. Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
  4. If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.

Follow-up

  • The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
  • How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?

Stop tag and share joins from fanning out a page

Medium · join fan-out · semi-joins · many-to-many

resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.

Approach

  1. Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
  2. Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
  3. Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
  4. Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.

Follow-up

  • The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
  • A resource can be shared with the same user twice under different permissions. Does your count change, and should it?

Write the update path that detects a concurrent edit

Medium · optimistic concurrency · transactional outbox · audit history

resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.

Approach

  1. One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
  2. Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
  3. State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
  4. Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.

Follow-up

  • A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
  • Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?

Explain the core pillars of Object-Oriented Programming (OOP) and provide a practical example.

Medium · Technical and Domain Knowledge

Approach

  1. Name the four pillars and give each a one-line definition: encapsulation (state is private and changes only through methods that keep invariants), abstraction (callers depend on what an object does, not how), inheritance (a subtype reuses and specialises a supertype), and polymorphism (one call site, behaviour chosen by the runtime type).
  2. Use one running example for all four. In Java: an Account class with a private balance and a withdraw() that rejects overdrafts (encapsulation); a PaymentMethod interface with pay(amount) (abstraction); an abstract AbstractPayment class that implements it and holds shared validation, such as rejecting a non-positive amount, which CardPayment and BankTransfer extend and reuse while each overrides only its own transfer step (inheritance; implementing the interface alone would show subtyping, not reuse); and checkout code that calls pay() without knowing which one it holds (polymorphism).
  3. Separate the two kinds of polymorphism: overriding is resolved at runtime by dynamic dispatch on the object's type, while overloading is resolved at compile time from the argument types. Mixing them up is a common slip.
  4. Add the trade-off: deep inheritance trees couple subclasses to parent internals (the fragile base class problem), so I prefer composition and interfaces, and I keep subtypes substitutable (Liskov: Square extending a mutable Rectangle breaks callers that set width and height separately).
  5. Tie it to code you have written: name one class you designed, which invariant its encapsulation protected and where an interface let you swap an implementation, for example a mock in a unit test.

Follow-up

  • In Java, when would you choose an abstract class over an interface, given that interfaces can have default methods since Java 8?
  • What is the difference between overloading and overriding, and which one is decided at compile time?
  • Show a case where inheritance caused a bug and how composition would have avoided it.

What are the key differences between REST and SOAP APIs?

Medium · Technical and Domain Knowledge

Approach

  1. Start with the category difference: SOAP is a protocol with a fixed XML message format (Envelope, optional Header, Body, and a Fault element for errors), while REST is an architectural style built on resources identified by URIs, the HTTP methods, stateless requests and cacheable responses.
  2. Compare contracts and formats: SOAP services are usually described by a WSDL from which clients generate stubs, and the payload is always XML. REST has no mandatory contract (OpenAPI is the common way to write one) and can use any representation, most often JSON.
  3. Compare transport and error handling: SOAP is transport-independent (usually HTTP POST, but also JMS or SMTP) and returns errors as SOAP Faults; REST relies on HTTP itself, so status codes (400, 404, 409, 500), method semantics (GET, PUT and DELETE are idempotent, POST is not) and HTTP caching of GET responses all carry meaning.
  4. Compare the enterprise features: SOAP has the WS-* standards for message-level security (WS-Security), reliable delivery and distributed transactions, which explains its presence in older banking, telecom and enterprise integrations. REST is lighter, easier to call from browsers and mobile clients, and relies on TLS and OAuth/JWT for security at the transport and token level.
  5. Close with when you would pick each and how you would build it: REST for new public or internal APIs (in Java, a Spring @RestController), SOAP when integrating with an existing WSDL-defined service (JAX-WS or Spring Web Services). Mention a real integration you have done with either one.

Follow-up

  • What makes an API actually RESTful rather than just JSON over HTTP? Think of statelessness, resource modelling and hypermedia.
  • Which HTTP methods are idempotent, and how would you make a POST that creates a payment safe to retry?
  • How would you version a REST API, and how does that compare with changing a WSDL contract?

How do you approach debugging a complex issue in a production environment?

Medium · Technical and Domain Knowledge

Approach

  1. Start with impact and mitigation before root cause: who is affected, since when, and whether a rollback, feature-flag switch or failover stops the damage now. Restoring service and finding the cause are separate steps.
  2. Build a timeline of what changed: deploys, configuration, dependency versions, traffic shape, data volume, upstream services and certificates. Correlate the first error timestamp with those events.
  3. Gather evidence instead of attaching a debugger to production: logs filtered by a correlation or request id, metrics (error rate, latency percentiles, CPU, memory, GC, connection-pool use), traces across services, and a heap or thread dump if the symptom is a leak or a hang.
  4. Form one hypothesis at a time and test it with the cheapest check that rules something out: reproduce in a staging environment with production-like data or config, bisect commits between the last good and first bad build, or add targeted logging behind a flag. Treat intermittent failures as likely races, timeouts or resource exhaustion.
  5. Close it properly: fix with a regression test that fails without the fix, verify on the production metrics that the symptom is gone, then write a blameless postmortem with the cause, the detection gap and one or two concrete preventive actions.

Follow-up

  • The bug only appears under production load and you cannot reproduce it locally. What do you do next?
  • You are working on a client's system and do not have direct access to their production logs. How do you still make progress?
  • How would you tell whether the deploy caused the problem or only coincided with it?

Suggested practice checklist

The plan follows the five reported questions, the reported evaluation areas (data structures, design patterns, architecture, trade-offs), the listed Spring, transaction and React topics, and the consultant side of the process. Days 2 to 5 are technical, day 6 is spoken answers, day 7 is a full run.

Day 1 — Confirm the loop and map your CV

  • Send the recruiter a short list of questions: which project or client the role is for, which stages to expect, and whether there is an online assessment or live coding.
  • List every project on your CV and write the key technical decision, the alternative you rejected and the outcome next to each.

Deliverable: A question list sent to the recruiter and a one-page CV sheet with a decision, an alternative and an outcome per project.

Day 2 — OOP and design patterns

  • Write the answer to the OOP pillars question with a single worked example in your main language that shows all four pillars, using an abstract base class for the inheritance part.
  • Implement a thread-safe Singleton, a Factory and an Observer in your main language, each with a two-sentence note on when you would use it and when it would be overkill.

Deliverable: A written OOP answer with its example plus three small pattern implementations with usage notes.

Day 3 — Processes, threads and concurrency

  • Write the spoken answer to the process-versus-thread question: memory, creation cost, communication, failure isolation and a use case for each.
  • Write a small program with two threads updating a shared counter, show the race, then fix it with a lock or an atomic type.
  • Solve the overlapping job attempts and peak concurrency practice problem.

Deliverable: A race condition demo with its fix, a prepared answer, and one solved concurrency practice problem.

Day 4 — Data structures and algorithms

  • Write reverse a linked list, binary search and merge sort from memory in your main language and state the time and space complexity of each.
  • Work through the event batch high-water mark practice problem, naming the data structure you chose and why.

Deliverable: Three algorithms written without references, with complexities, plus one solved practice problem.

Day 5 — APIs, Spring transactions and React

  • Build a comparison table of REST and SOAP covering contract, message format, state, caching, security and error handling, and write a spoken answer on when you would pick each.
  • Write a one-page note on ACID and isolation levels, then on Spring's @Transactional: propagation REQUIRED (join the current transaction) versus REQUIRES_NEW (suspend it and start a new one), rollback by default only on unchecked exceptions unless rollbackFor is set, and the self-invocation pitfall where a call to this.method() bypasses the proxy and runs without a transaction.
  • Review React: state versus props, useEffect dependency arrays and cleanup, stable keys in lists, then build a small component that calls the Spring REST endpoint from your REST answer, with loading and error states and the CORS setup the backend needs (@CrossOrigin or a global CORS configuration).
  • Solve the concurrent edit detection practice problem and explain optimistic locking in your own words.

Deliverable: A REST versus SOAP table, a one-page transaction and @Transactional note, a small React component calling a REST endpoint, and a solved concurrent edit exercise.

Day 6 — Debugging and your version control story

  • Rehearse the production debugging answer out loud using impact, recent change, logs and metrics, reproduction, hypothesis, rollback or fix, and postmortem.
  • Write the version control and branching story in STAR form, with the model, the trade-off, a conflict you resolved and the result.
  • Outline a production incident you owned from the alert to the postmortem.

Deliverable: A recorded debugging walk-through, a written STAR story on branching and one incident outline.

Day 7 — Consultant mindset and full run

  • Write short answers about working at a client site, adapting to a new team's tools and learning an unfamiliar domain, each with a real example.
  • Prepare an example of disagreeing with a design decision and what you did after it was settled.
  • Run one full mock: your story, five reported questions answered aloud, one coding task, then write the questions you will ask about the team, the client and the first months.

Deliverable: Three consultant-style answers, one disagreement story and a completed mock with a list of questions to ask.

Behavioural preparation

Candidates report that the behavioral side looks at consultancy fit: flexibility about location, adapting to a client's way of working, communication that holds up between ALTEN managers and client technical leads, and the reasoning behind your past technical choices. Use the STAR structure (situation, task, action, result) and keep the situation short. Stories where you made the decision and can name the trade-off work best.

  1. Walk me through a past project and the trade-offs you made, such as performance against maintainability.
  2. Tell me about a time you had to learn an unfamiliar domain or codebase quickly to deliver.
  3. How would you handle working on site at a client in a different location, with a team that has its own tools and habits?
  4. Describe a disagreement with a technical lead on the client side and how it ended.

Describe your experience with version control systems and branching strategies.

Medium · Technical and Domain Knowledge

Approach

  1. Choose a real project where you were involved in choosing or changing the workflow, not just following it. Open with the setting in two sentences: team size, how often you released, and whether there were long-lived or client-specific branches.
  2. Name the model you used and why it fit: trunk-based development with short feature branches and feature flags, GitHub-flow style pull requests into main, or Git Flow with develop, release and hotfix branches for scheduled client deliveries. Say what the choice traded away, for example long-lived branches mean painful merges while trunk-based work needs strong automated tests.
  3. Cover the mechanics you handled: protected main, required review and CI checks before merge, tagging releases, a hotfix branched from the released tag and merged back, and merge versus rebase versus squash with the reason you picked one. Mention a conflict or a bad merge you resolved, and that you used revert on shared history rather than a force push.
  4. Close with the result and one lesson, such as fewer integration surprises or faster reviews, and what you would change. The mistake that sinks this answer is a list of Git commands with no decision or consequence attached; another is claiming experience with a tool you cannot discuss in detail.

Follow-up

  • When would you rebase instead of merge, and what must you never rebase?
  • A faulty commit has already been pushed to the shared main branch. What do you do?
  • If a client's team used a different workflow, or a different version control system, how would you adapt on your first week?

Narrate an outage you owned from page to postmortem

Hard · incident response · blast radius · postmortems

Pick an incident you personally drove, ideally one where writes were affected rather than reads. In six to eight minutes: state the symptom as it first appeared on a dashboard, the blast radius you established before you knew the cause, the mitigation you applied and when, the mechanism you eventually proved, and the follow-up that would prevent a repeat. Bring numbers: error rate, tenants affected, minutes to mitigate, minutes to resolve. If you cannot name what you measured, choose a different incident.

Approach

  1. Open on the signal rather than the cause: which metric at which percentile moved, on which service, at what time, so the listener follows the same evidence you had rather than a conclusion you already reached.
  2. Separate mitigation from diagnosis out loud. State what you did to stop the bleeding (flag off, shed traffic, drain a lease, roll back a deploy) and say plainly that you did it before the mechanism was known, because those are two jobs with different deadlines.
  3. Establish blast radius in countable terms: how many tenants, how many writes, and crucially whether the effect was loss or only delay. An append-only revision table or a pending outbox row means the change survived and the projection was merely behind, which is a repair rather than a data-loss incident.
  4. Prove the mechanism instead of asserting it. Name the trace span that grew, the plan that flipped to a sequential scan, the lease that expired, plus one alternative you ruled out and the signal that stayed flat while you ruled it out.

Follow-up

  • What would you do differently in the first five minutes, given the same dashboard and no more information?
  • Which follow-up action did you deliberately not take, and why was dropping it the right call?

Argue against a design, lose, and commit anyway

Medium · disagreement · service boundaries · decision records

Describe a design you argued against and lost. State the failure you predicted as a named mechanism, not a feeling about complexity: two services that would need one transaction, a projection with no rebuild path, a write path with no idempotency key. Say what evidence you brought, what the decision maker weighed instead, and what you did after the decision was made: what you instrumented, what you wrote down, and whether the prediction came true. Five minutes.

Approach

  1. State the prediction in falsifiable form up front: the mechanism, the condition that triggers it, and the observable outcome. A prediction that cannot be checked also cannot be credited to you later.
  2. Show the evidence you had at the time and label each piece honestly as measured, analogous, or intuition. Keeping the intuition is fine; disguising it as data is the thing that erodes your standing in the next argument.
  3. Represent the opposing case at full strength, including the constraint you did not control: a fixed date, a team boundary, or the fact that the decision was cheap to reverse and yours was not.
  4. Make disagree-and-commit concrete. Name the artefact you left behind so the prediction could be settled without you: the alert and its threshold, the counter on the dashboard, the decision note that recorded the trade-off and the condition that would revisit it.

Follow-up

  • What threshold on that alert would have proved you right, and did anyone ever look at it?
  • If the same proposal arrived tomorrow with the same deadline, would you argue it the same way?