Interview guides · AllRock Consulting
AllRock Consulting Software Engineer Interview Guide
AllRock Consulting Software Engineer interview guide: reported sensor-data design, SQL tuning and debugging questions, a 7-day plan and behavioral prep.
The 60-second brief
AllRock Consulting is described by candidates as a consulting firm working in geotechnical and environmental engineering. Software is part of how it models site data, visualizes it and delivers results to clients. A Software Engineer builds and maintains the internal tools around that work: systems that take in data collected on site, screens and charts for viewing it, and automation for producing reports. The day-to-day counterparts reported for the role are geotechnical engineers and environmental scientists, so the users of your software are engineers and scientists rather than other programmers.
This guide is for candidates interviewing for a Software Engineer position at AllRock Consulting. It covers the five questions candidates report (designing for large volumes of field sensor data, troubleshooting a production bug, choosing languages and frameworks, keeping code maintainable for mixed audiences, and tuning a slow database query), the stack candidates describe (Python, C# or Java, SQL, Git, with GIS and Azure or AWS as extras), and the behavioral and communication preparation that fits a consulting setting. No round order is reported, so the guide is organised by preparation area rather than by stage.
Candidates report a structured process that moves from initial screenings to technical deep dives and behavioral conversations with senior leadership, usually finishing within 3 to 5 weeks. The number and order of individual rounds are not reported, so confirm them with your recruiter.
Focus areas
- Software Engineering (General)
- Geoscience Data Handling (Domain Knowledge)
- Geotechnical Engineering Concepts
Overview
The reported questions share one theme: ordinary software engineering applied to measured data from the physical world. One question asks how you would process large volumes of sensor data from the field, and the evaluation areas candidates describe include schema design for periodic high-frequency sensor updates, data validation and error handling, API security, real-time telemetry and cloud storage. Example scenarios include a schema for remote environmental sensors and a system failure during a data collection phase. Prepare to reason about data that arrives late, duplicated, out of order or wrong, because that is what field data does.
The remaining reported questions are general engineering judgment: troubleshooting a complex bug in production, choosing between languages or frameworks for a new project, keeping code maintainable and scalable for teammates with different technical backgrounds, and optimizing a slow database query. None of them needs domain knowledge to answer, but each is stronger when you tie it to a concrete system you built. Candidates also report topic areas in geoscience data handling and in geotechnical and environmental concepts. You are not expected to be an engineer, but learn the vocabulary well enough to ask what a measurement means.
The stack candidates describe is Python, C# or Java, SQL and Git, with GIS software and Azure or AWS listed as useful extras. Pick the language you are strongest in and be ready to write real code in it, and be ready to read and write SQL against a time-series style table. Documentation is also reported as important for the role, so bring an example of a README, a data dictionary or a runbook you wrote and say who used it.
Because the colleagues you would build for are engineers and scientists, communication is part of preparation, not an add-on. Practise explaining a technical choice, such as why a reading was rejected or why a report is a day late, to someone who does not write code. Candidates also describe an expectation to ask about the team's current software problems, so write your questions ahead of time.
Where to focus your preparation
No fixed round sequence is reported for AllRock Consulting, so the loop is presented as one preparation step covering the reported technical, behavioral and communication areas.
Preparation focus
Candidates describe a structured process that runs from initial screenings through deep technical evaluations to behavioral interviews with senior leadership, usually completed within 3 to 5 weeks, with some variation by office and by how urgent the project need is. How many rounds there are, their order and their formats are not reported, so this single step stands for the whole loop. Treat it as a checklist: confirm the format with the recruiter, then prepare each reported question type. The technical questions are a field-data system design, a language and framework choice, maintainability practices and slow-query tuning; the behavioral side is a production bug story and communication with non-technical colleagues. For coding, say your reasoning aloud as you go, since candidates report that how you reach an answer matters alongside the result.
What to demonstrate
- Software design for field sensor data: schema, ingestion, validation and failure handling
- Everyday engineering judgment: language choice, code maintainability, SQL performance
- Troubleshooting experience from real production systems
- Clear explanation of technical ideas to colleagues from geology or civil engineering backgrounds
How to prepare
- Ask the recruiter for the sequence of stages, whether you will write code live, and which language you may use
- Work the sensor-data design question end to end: ingestion, storage schema, validation, failure handling and security, then say it aloud
- Prepare one production-bug story and one example of explaining a technical trade-off to a non-programmer
- Read the job posting for location requirements and write down questions about the team's current software challenges
Where candidates lose points
Answering the sensor-data design question with a generic web-service diagram and no treatment of bad data
Cover the data's own problems explicitly: duplicate and out-of-order readings, late-arriving batches, sensor drift or missing values, and what happens when a device or the network drops mid-collection. State where you validate, what you quarantine instead of discarding, and how a correction is traced.
Proposing a schema without naming the key, the time column or the query it must serve
Say what one row represents, the primary or composite key (sensor, timestamp), how you index for 'readings for this site in this window', and when you would partition by time. Add a column for raw value versus validated value, and for units.
Tuning a slow query by guessing at indexes
Describe the sequence: capture the exact query and its plan, find the scan or join that dominates, check row estimates against reality, then change the index, the predicate or the query shape, and re-measure. Mention the cost an extra index adds to writes on a table that receives constant sensor inserts.
Choosing a language or framework from habit, with no stated criteria
Name the criteria before the answer: team skills, library support for the work (data handling, GIS, reporting), hosting target such as Azure or AWS, hiring and maintenance cost, and performance needs. Then show how they point to a choice for one concrete project, including what would change your mind.
Explaining technical work in programmer language to listeners from geology or civil engineering
Practise a version of each answer that opens with the effect on a field engineer's decision and leaves out jargon. Use a plain example, such as a reading that is rejected and why, and check that a non-programmer friend can repeat it back.
Questions & practice
What criteria do you use to choose between different programming languages or frameworks for a new project?
Medium · Technical Proficiency and Problem Solvin
Approach
- Start from the constraints, not from a favourite language: what the software does (numerical processing, a web app, a desktop tool, an integration), where it runs, what it must talk to, and who maintains it after you hand it over.
- Name concrete criteria and weigh them: library ecosystem for the problem (Python's NumPy, pandas, GeoPandas and Shapely for data and spatial work; C# and .NET for Windows desktop tools and Azure integration; Java for long-running JVM services), the team's existing skills, performance needs, interoperability with existing systems, licence terms, and maturity and long-term support.
- Treat performance as something to measure, not assume. For example, standard CPython builds run one thread of Python bytecode at a time because of the GIL, so CPU-bound work needs vectorised libraries or multiprocessing. That matters only if a prototype shows the hot path is CPU-bound.
- Reduce risk with a short spike on the hardest requirement (parsing a messy file format, a GIS operation, a throughput target) and record the choice, the alternatives and the trade-off accepted in a short decision record kept in Git.
- Close with a real example in first person: 'I chose Python over C# for a data-processing tool because the parsing and plotting libraries already existed and the people maintaining it knew Python; I accepted slower raw execution and checked that it met the volume.' Avoid answers that justify a choice by novelty alone.
Follow-up
- When would you pick a language the current team does not know?
- Your prototype shows the chosen stack is too slow for the data volume. What do you do next?
- How do you migrate an existing tool if the earlier language choice turns out to be wrong?
Merge partitioned event streams into one ordered feed with bounded lateness
Hard · k-way merge · watermarks · out-of-order streams
The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.
Approach
- Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
- Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
- Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
- Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.
Follow-up
- The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
- The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?
Track a rolling failure rate per destination for circuit decisions
Easy · sliding window · ring buffer · circuit breaker
The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.
Approach
- Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
- Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
- State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
- Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.
Follow-up
- The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
- A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?
Explain your process for optimizing a slow-performing database query.
Medium · Technical Proficiency and Problem Solvin
Approach
- Reproduce before changing anything: capture the exact statement with realistic parameters and find it from data, not guesswork (pg_stat_statements in PostgreSQL, Query Store in SQL Server). Then get the actual plan: EXPLAIN (ANALYZE, BUFFERS) in PostgreSQL, or the actual execution plan in SQL Server.
- Read the plan for the expensive node: sequential scans on large tables, a nested loop over a large outer input, sorts or hashes spilling to disk, and estimated rows far from actual rows. A large estimate gap points to stale statistics, so run ANALYZE (PostgreSQL) or UPDATE STATISTICS (SQL Server) before adding anything.
- Fix access paths: a composite index with equality columns first and the range column last, such as (sensor_id, recorded_at) for 'one sensor over a date range'; a covering index (INCLUDE) to avoid table lookups. Make predicates sargable: rewrite DATE(recorded_at) = '2026-01-01' as a half-open range, avoid implicit type casts, and note that LIKE '%term' cannot use a B-tree index.
- Fix query shape: select only the columns you need, filter before joining and aggregating, replace correlated subqueries with joins or EXISTS, use keyset pagination instead of large OFFSETs, and for time-series tables rely on time partitioning for pruning or precomputed rollups for dashboards.
- State the trade-offs and verify: every index slows inserts and takes storage, which matters on a table that receives constant writes. Re-run the plan and timing after each single change, and watch for parameter-sensitive plans where one cached plan fits some inputs badly.
Follow-up
- The query uses the index in testing but not in production. What could explain that?
- The table takes continuous inserts. How do you decide how many indexes it can afford?
- The plan is already optimal but the query is still too slow for a dashboard. What do you change next?
Denormalise tenant onto revisions and backfill it live
Hard · denormalisation · online migration · backfill
resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.
Approach
- Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
- Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
- Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
- Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.
Follow-up
- The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
- How do you verify the backfill actually finished, given rows are still being inserted while it runs?
How would you design a system to process large volumes of sensor data from the field?
Medium · Technical Proficiency and Problem Solvin
Approach
- Size it before designing: number of sensors, readings per second, payload size, and whether field links drop out. For example, 10,000 sensors sending 100-byte readings once a second is about 1 MB/s, or roughly 86 GB a day of raw data. Then separate the two consumers: threshold alerts that need low latency, and reports and maps that can tolerate minutes of delay.
- Ingestion: gateways buffer readings locally and upload in batches with a per-device sequence number. The endpoint authenticates each device over TLS and appends to a durable log (Kafka, Kinesis or Azure Event Hubs) partitioned by sensor id, which keeps each sensor's readings in order. Delivery is at-least-once, so writes are idempotent on (sensor_id, sequence) or (sensor_id, timestamp).
- Validation as its own stage: schema and unit checks, physical range checks, timestamp sanity (clock drift, future dates). Flag or quarantine suspect readings rather than silently dropping them, and keep raw values next to corrected ones so any correction can be audited.
- Storage: a time-series table keyed on (sensor_id, recorded_at) and partitioned by time (PostgreSQL native partitioning or TimescaleDB), raw files in object storage as Parquet for reprocessing, and precomputed hourly or daily min/max/avg rollups for dashboards. Use event time, not arrival time, so late backlogs land in the right window.
- Operations: track last-seen time per sensor to detect silent devices, alert on queue lag, and set a retention policy (raw kept N days, rollups longer). The trade-off to state: batching at the gateway saves bandwidth and survives outages, but it raises alert latency.
Follow-up
- A gateway is offline for two days and then uploads its whole backlog at once. What happens to ordering, rollups and alerts?
- A calibration error is found and a month of readings must be corrected. How do you reprocess without losing the original values?
- How would you detect a sensor that keeps reporting plausible but stuck values?
How do you ensure your code is maintainable and scalable for team members with varying technical backgrounds?
Medium · Technical Proficiency and Problem Solvin
Approach
- Separate domain logic from I/O and UI: keep calculations as pure functions that take values and return values, so a colleague who knows the engineering but not the codebase can check a formula without reading file handling or database code.
- Make units and assumptions explicit: put units in names or types (depth_m, pressure_kpa), give docstrings that state inputs, units and the source of each formula, and validate inputs at the boundary with error messages a non-developer can act on.
- Automate consistency so reviews focus on logic: a formatter and linter in CI (Black or Ruff for Python, dotnet format for C#), type hints checked by mypy, and small pull requests in Git with a description of what changed and why.
- Test with known answers: cases worked out by hand or taken from a reference, which a domain expert can read and confirm, plus edge cases such as empty input, missing values and boundary values. Tests let others change the code without fear.
- Scale without over-engineering: move constants into configuration, put interfaces only where a second implementation is realistic, and say the trade-off. Every extra layer of abstraction makes the code harder to read for people outside software, so I add one only when it removes real duplication or isolates something likely to change.
Follow-up
- A reviewer can verify the maths but cannot read the code. How do you structure the review?
- Give an example where you removed an abstraction because it made the code harder to follow.
- You inherit an untested script the whole team depends on. What do you do first?
One customer endpoint stalls deliveries to every other destination
Medium · bulkhead · timeouts · saturation
The egress service delivers about 1.5k webhooks/second across 40,000 destinations, with a per-destination concurrency cap of 4 and a 10-second connect-plus-read timeout. Throughput falls to 300/second, queue depth climbs, and p99 delivery latency for unaffected destinations goes from 200 ms to minutes, while the error rate barely moves. One tenant holds 900 destination rows whose URLs share a hostname that now answers in 9.5 seconds. Explain the mechanism with the arithmetic, then give the containment in the order you would apply it.
Approach
- Look at saturation before errors. A flat error rate with collapsing throughput says nothing is failing, things are waiting, so the first signal to pull is in-flight request count or pool wait time rather than the error counter. This is the distinction that decides the whole investigation.
- Group in-flight work by resolved host, not by destination id. The cap is keyed per destination row, so 900 rows sharing one hostname buy 3,600 concurrent slots against a single host, each held for 9.5 seconds. The bulkhead was never a bulkhead for that host, and grouping by the wrong dimension is why the dashboard looked healthy.
- Do the arithmetic in both directions. Required concurrency is arrival rate times latency, so 1.5k/second at 200 ms needs about 300 in flight, which is entirely consumed by 3,600 slow slots; conversely whatever concurrency is left sustains rate equals concurrency divided by 9.5 seconds, which is the 300/second you are seeing. Matching both numbers is what promotes this from a plausible story to the mechanism.
- Explain why the circuit breaker never helped. It opens on consecutive failures, and a 9.5-second response inside a 10-second timeout is a success. Slow is not failing, so an error-rate breaker cannot see this; you need a slow-call ratio, a deadline propagated from the caller's remaining budget, or a concurrency limiter.
Follow-up
- The host recovers to 80 ms. How long does the queue take to drain, and what does the drain do to the recovered host?
- Where should the 10-second timeout number actually come from?
Suggested practice checklist
The plan starts by confirming the format, then works through the reported technical questions (query tuning, sensor-data design, language choice, maintainability), then the production-bug story and communication practice, and ends with a full mock. Practice-library questions are attached where they exercise the same skills.
Day 1 — Confirm the format and map the stack
- Email the recruiter to ask for the sequence of stages, whether coding is live, which languages are allowed and whether the role is hybrid at your location.
- List the stack candidates describe for the role (Python, C# or Java, SQL, Git, plus GIS and Azure or AWS as extras) and mark which you can discuss with a real project behind it.
Deliverable: A sent message to the recruiter and a one-page stack map with a project example next to each item you will claim.
Day 2 — Slow database query tuning
- Take a slow query you have run, or write one against a large readings table with a join to a sites table. Capture the execution plan and mark the costliest step.
- Write the tuning sequence you would say aloud: reproduce, read the plan, check row estimates, change the index or query shape, re-measure, and note what the new index costs on insert-heavy tables.
Deliverable: A written plan comparison for one query (before and after) plus a spoken answer to the tuning question.
Day 3 — Design for large volumes of field sensor data
- Sketch an architecture for remote sensors sending periodic high-frequency readings: device or gateway, ingestion endpoint, queue, storage, validation step and reporting layer.
- Write the table schema for readings and sensors with keys, time column, units and a raw-versus-validated flag, and the three queries it must serve.
- Answer the scenario of a system failure during data collection: describe buffering at the device, idempotent writes and how you backfill gaps.
Deliverable: One architecture diagram, one schema with its main queries, and a spoken answer covering failure handling and API security.
Day 4 — Language choice and maintainable code
- Write your decision criteria for picking a language or framework, then apply them to two projects (for example a reporting tool and a telemetry ingester).
- Take a module you wrote and list what a teammate from a different background would struggle with. Fix three things: names, structure, tests or documentation.
- Write a short README with setup, data inputs and a data dictionary for that module, as a geoscientist would need it.
Deliverable: A criteria list applied to two projects and a README for one module, with before-and-after notes on the code changes.
Day 5 — Production troubleshooting story
- Write your production-bug story using the sequence: symptom, impact, diagnosis steps, mitigation, root cause, prevention, one measured result.
- Say it aloud and cut it down until you can tell it clearly, then record the answer to the follow-up on how you confirmed the cause.
Deliverable: A written story with a measured result and a recorded spoken version.
Day 6 — Domain vocabulary and communication
- Read an overview of how geotechnical and environmental site data is collected (boreholes, groundwater or air monitoring, GIS maps) and note ten terms with a one-line meaning.
- Rehearse explaining one technical decision, such as rejecting a bad reading, to a listener with no software background, in under a minute of speech.
- Write five questions about the team's current software challenges and how its data reaches engineers.
Deliverable: A ten-term glossary, a recorded plain-language explanation and a list of five questions to ask.
Day 7 — Full mock
- Run a mock with a friend: one design question (sensor data), one query-tuning question, one behavioral story and a code review of your own README.
- Keep a list of hesitations and weak spots and fix the two largest.
- Rewrite your closing questions and check that your stack claims all have a real project behind them.
Deliverable: A completed mock, a list of two fixes made and a final set of questions to ask.
Behavioral preparation for field-data engineering work
Candidates report behavioral conversations with senior leadership and an emphasis on communicating with non-technical stakeholders and handling ambiguity in a consulting setting. Rehearse stories that show you made the decision, explained it clearly to people outside software, and checked that your data was right.
- Tell me about a time you explained a technical decision to someone without a programming background.
- Describe a project where the requirements were unclear. How did you decide what to build first?
- Walk me through a time you found bad or missing data in a system you owned and what you did about it.
- Tell me about a deadline you had to protect or renegotiate, and how you decided what to cut.
- Why do you want to build software for engineering and environmental work?
Describe a time you had to troubleshoot a complex bug in a production environment.
Medium · Technical Proficiency and Problem Solvin
Approach
- Choose a bug you personally diagnosed in a system real users depended on. Open with two sentences: what broke, who noticed, and how you found out (an alert, a ticket, a call from the field). Skip code detail at the start.
- Spend most of the answer on the diagnostic sequence. Say what you checked first (recent deploys, logs, metrics, the one input that failed), how you narrowed to a component, how you reproduced the fault or added logging when you could not, and which hypotheses you ruled out and by what evidence.
- Separate mitigation from root cause. State what you did to stop the damage (rollback, feature flag, manual correction of bad records, pausing a job) and when, then the actual cause and the fix.
- Finish with prevention and a number: the regression test, the new alert or validation check, the runbook entry, and one measured result such as records affected, time to mitigate or error rate before and after.
- For this role, an example involving data (wrong, missing or late records, a bad import, a slow query) fits well. Say how you explained the problem to the people relying on that data, in terms they could act on. The mistake that sinks the story is describing what the team did without saying what you decided, or ending at 'it was fixed' with no cause.
Follow-up
- How did you confirm that was the root cause and not a coincidence?
- What did you tell the non-technical people affected while it was still broken?
- What monitoring or test would have caught it earlier, and did you add it?
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
- 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.
- 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.
- 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.
- 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?
Tell callers you do not own that their integration breaks
Medium · deprecation · compatibility · stakeholders
A field in a write endpoint's response must change shape. You own the endpoint; you do not own the four internal callers or the outbound webhook consumers who read it. Describe a deprecation you were responsible for: what you shipped first, how you established who was actually reading the field, the window you gave and what set its length, what you did about the consumer who never moved, and how you decided removal was safe. Name the signal you used, not the announcement you sent.
Approach
- Establish the reader set empirically rather than from a wiki of owners: per-field usage counters keyed by principal, or access logs attributed to a consumer. State the blind spot of whichever you pick, since a consumer that reads the field only on a monthly job will not appear in a week of logs.
- Ship additive first. Populate the new field alongside the old one so no reader is forced to move, which is also what keeps a rolling deploy safe, because old and new instances answer the same requests at the same time and a rollback must still find the old shape present.
- Set the window from the slowest legitimate consumer's release cadence, not from your calendar, and decide separately what to do for a consumer with no release process at all, such as an external webhook endpoint you can only email.
- Convert silence into evidence before you rely on it: a short, low-traffic removal window that makes a still-dependent consumer fail visibly and loudly while you are watching, rather than at three in the morning after you have moved on.
Follow-up
- How would you detect a consumer that reads the field only during a monthly export?
- One caller refuses to move and has a commercial relationship behind it. What changes in your plan and what does not?