Interview guides · American Operations
American Operations Software Engineer Interview Guide
American Operations Software Engineer interview guide: two reported rounds, COBOL, DevSecOps and legacy modernization questions, plus a 7-day prep plan.
The 60-second brief
Candidates describe American Operations as an organization whose engineers look after digital infrastructure. The work they name includes COBOL modernization, DevSecOps pipelines and Facility and Equipment Management (FEM) systems, and the teams they mention range from UC/Voice Engineering to Release Train Engineering. Maximo and CI/CD tooling come up as part of the stack, and Java and Python are listed for development roles. For a Software Engineer this means keeping older systems running while changing them safely, and building the delivery and security automation around them.
This guide is for candidates interviewing for a Software Engineer role at American Operations. It covers the two reported rounds, Initial Screening and Technical Evaluations, and the nine reported questions on legacy modernization, DevSecOps, production debugging, scalability and engineering trade-offs. It does not cover pay, and it makes no claim about any one team's exact format, because candidates say the technical focus varies by team.
Candidates report two rounds over roughly 2-4 weeks: an Initial Screening, then Technical Evaluations built around practical experience and engineering principles. Timing and focus are reported to vary by team and by security clearance requirements.
Focus areas
- DevSecOps
- Software Engineering
- Security in Software Delivery
Overview
The reported questions share one theme: change a system that already matters without breaking it. You are asked how to modernize a legacy system with zero downtime, what goes wrong when a modern application meets a legacy database, how to keep a voice or communication system up under high load, and how to debug a complex failure in production. Each answer is stronger with a concrete project behind it, so pick two or three systems you have really worked on and know them down to the failure modes.
The second group is judgment under constraints: balancing rapid feature delivery against long-term maintainability, choosing which technical debt to pay down when stakeholders disagree, and describing a time you optimized an underperforming system and which metrics proved it. Candidates also report prompts about DevSecOps pipelines and about troubleshooting without the original documentation. These reward a clear structure: the situation in two sentences, your decision, the evidence, and the result.
The stack matters. Candidates name COBOL, Maximo, CI/CD tooling and DevSecOps for role-specific discussions, and Java or Python for development roles. You will not know every item, so decide in advance how to describe adjacent experience honestly. For example, if you have not touched COBOL, explain how you have worked in a codebase you inherited and what you did to make a first change safe.
Candidates also report that the loop leans on past projects: the reasoning behind architectural decisions and how you handled unexpected failures. Expect to explain trade-offs aloud rather than recite syntax, and prepare example scenarios such as reviewing a code change to a system that cannot go down, or resolving a dependency conflict in production.
The American Operations interview process
Candidates describe a two-stage loop. The descriptions below say what is reported for each stage, then how to prepare for it.
Initial Screening
Candidates describe the Initial Screening as a set of discussions about your qualifications and fit for the role. Reports do not list specific questions for this stage, so treat it as the place where your background has to connect to the stack in the posting, such as COBOL, Maximo, DevSecOps or CI/CD. Have a short, concrete account of your last two projects and what you personally owned. Because candidates say many roles are location-specific and timing can depend on security clearance requirements, ask about both early.
What to demonstrate
- How your experience maps to the stack and team named in the role
- Whether you can describe a project you owned end to end
- Clarity when summarizing your own technical decisions
How to prepare
- Write a two-minute walk through your career that ends on the legacy, DevSecOps or reliability work most relevant to this role.
- Pick one project and be ready to explain the why behind its architecture and one failure you handled.
- List the posting's stack items, mark which you have used, and prepare an honest bridge for the ones you have not.
- Prepare questions on the team's current technical challenges, location requirements and any clearance steps.
Technical Evaluations
Candidates describe Technical Evaluations as deep-dive technical discussions about practical experience and engineering principles. Reported topics include modernizing a legacy system with zero downtime, integrating modern applications with legacy databases, scaling a voice or communication system, debugging a production failure, and security testing inside an automated build. Candidates also mention example scenarios such as reviewing a change to a critical system and resolving a dependency conflict in production. Prepare by telling each answer as a sequence of decisions with trade-offs, drawn from systems you have actually run.
What to demonstrate
- Hands-on command of your primary languages, platforms and delivery tooling, explained through trade-offs
- How you reason about stability, failure modes and security in a technical decision
- Whether you can connect engineering choices to operational outcomes
How to prepare
- Outline a zero-downtime cutover for a legacy system: parallel run, incremental routing, data reconciliation and a rollback trigger.
- Write down the failure modes of a modern service reading from a legacy database: encodings, missing constraints, batch windows and lock contention.
- Rehearse a production debugging sequence aloud, from what changed to the smallest reproduction to the fix and the follow-up.
- Practise explaining a code review and a dependency conflict resolution for a system that cannot afford an outage.
Where candidates lose points
Describing a legacy modernization as a rewrite followed by a switch-over night
For the zero-downtime question, lead with incremental routing: run old and new in parallel, compare outputs, move traffic in slices, and define the rollback trigger and the data reconciliation check before the first cutover.
Answering the DevSecOps question with a list of scanners and no gate policy
Say where each check runs in the pipeline, what severity blocks a build, who owns suppressions, and one case where a gate caught or wrongly blocked something. Tie it to a pipeline you really ran.
Debugging a production failure by naming a theory first
Start with what changed and when, check that the monitoring is trustworthy, then narrow the failure with a split that rules out half the candidates. Separate the trigger from the cause and say what you would add so it is caught next time.
Giving a legacy-database integration answer that only says 'use an API layer'
Name the concrete hazards: character encoding and date formats, tables with no constraints, batch jobs that lock rows, and unclear ownership of the schema. Then say how you isolate them, for example with an anti-corruption layer, read replicas or change capture, and contract tests.
Telling trade-off and optimization stories without numbers or a stakeholder
For the speed-versus-maintainability, technical debt and underperforming-system questions, state the baseline metric, what you changed, the measured result, and who disagreed. A story with no measurement or no decision reads as observation.
Questions & practice
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
- 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.
- 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.
- 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.
- 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?
Identify the heaviest tenants in a five-minute window under memory pressure
Medium · top-k · heavy hitters · streaming
The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.
Approach
- Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
- Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
- State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
- Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.
Follow-up
- The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
- Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?
Archive a resource graph without breaking live references or recursing
Medium · graph traversal · topological order · tenant isolation
Resources reference other resources within a tenant; for the largest tenant the reference table holds up to 2,000,000 nodes and 8,000,000 edges. Archiving a resource must archive everything reachable from it that nothing outside the set still references, refuse when a live external referrer exists, and terminate when references form cycles, which they legitimately do. Produce the archive order and the refusal list, targeting O(V+E). Say what stops the traversal crossing a tenant boundary, and why recursion is the wrong control structure at this size.
Approach
- Load the subgraph with the tenant predicate on both endpoints of the edge, not only on the side you started from. Scoping the left table alone is the classic cross-tenant leak: one mis-entered edge then pulls another tenant's resources into the traversal and, worse, into the archive.
- Traverse iteratively with an explicit stack. A 2,000,000-node graph can hold a chain deep enough to exhaust a native stack in the low tens of thousands of frames, and that failure is a process crash rather than an error you can return.
- Treat cycles as data rather than corruption: compute strongly connected components with Tarjan in O(V+E) using its own explicit stack, then condense. The condensation is a DAG, so a topological order over it gives the archive order, and every member of a component archives in one transaction because no order within a cycle is valid.
- Decide refusals with reverse edges. A candidate is archivable only if every in-edge originates inside the candidate set, so build the transpose or count in-degrees restricted to the visited set, and emit each blocked resource with the id of the external referrer, which is the only part of the answer an operator can act on.
Follow-up
- The graph is read in one query and the archive writes a minute later. What can change in between, and how do you make the write safe?
- The candidate set is 400,000 resources. Is that one transaction, and if not, what does a half-finished archive look like to a reader?
Find version gaps and relay lag with window functions
Medium · window functions · event tables · frame semantics
outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.
Approach
- Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
- Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
- Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
- Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.
Follow-up
- Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
- Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?
Hold a per-tenant active cap against concurrent creates
Hard · write skew · isolation levels · constraints
A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.
Approach
- Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
- Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
- Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
- State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.
Follow-up
- A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
- The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?
How do you approach the modernization of a legacy system while ensuring zero downtime for end-users?
Medium · Technical Domain & Modernization
Approach
- Name the pattern: a strangler fig. Put a routing facade (reverse proxy or API gateway) in front of the legacy system. Move one bounded capability at a time to the new service and route only that slice to it, so the old path stays live as the fallback.
- Treat data as the hard part. Keep one system of record per entity and replicate with change data capture or a transactional outbox. Avoid application dual writes, because no single transaction spans both stores and the copies drift. Backfill first, then reconcile with row counts and per-key checksums.
- Change schemas with expand/contract. Add the new columns or tables, write to both shapes, backfill, switch reads, and only then remove the old shape. Every step stays backward compatible, so a rollback never needs a data migration.
- Verify before cutover. Run old and new in parallel on the same inputs and compare outputs; for a COBOL batch job that means diffing output records field by field. Then canary by percentage or user group behind a feature flag that switches traffic back instantly.
- Cover the edge cases: in-flight transactions and batch windows at the moment of cutover, ID or sequence collisions between the two systems, and encoding (EBCDIC to ASCII, COMP-3 packed decimal, which stores two digits per byte with the sign in the last nibble).
Follow-up
- Once writes have gone to the new system, how do you roll back without losing them?
- A nightly batch job reads and writes data that is half migrated. How do you keep it correct during the transition?
- What evidence from the parallel run would make you confident enough to cut over?
What are the primary challenges you have faced when integrating modern applications with legacy databases?
Medium · Technical Domain & Modernization
Approach
- Answer with one concrete integration story, then group the problems into categories: data representation, hidden business logic, concurrency, and capacity. Say what broke, what you changed and how you measured the fix.
- Data representation: fixed-width records, space-padded CHAR fields, dates stored as numbers (YYMMDD or Julian), EBCDIC text and packed decimals. Isolate all translation in an anti-corruption layer (an adapter or repository that maps the legacy schema to a clean domain model), so modern code never sees these quirks and the mapping can be tested in one place.
- Hidden logic: referential integrity and validation are often enforced in old application code, triggers or stored procedures rather than as constraints. Find them by reading the procedures, tracing writes, and writing characterization tests against masked samples of production data before changing anything.
- Concurrency and load: a modern service with a large connection pool can exhaust the legacy database's connections or cause lock contention with long-running legacy transactions. Cap the pool to what the database can serve, keep transactions short, and use optimistic concurrency with a version or timestamp column where one exists.
- Offload reads that do not need the system of record to a replica or a CDC-fed read store, and state the staleness that buys. Keep writes on one path so consistency questions have one answer.
Follow-up
- How did you discover business rules that existed only in triggers or old code?
- What did you do when the new application's traffic caused locking or timeouts on the legacy database?
- How did you keep the legacy database and the new application's own store consistent?
How do you ensure the scalability of a voice or communication system under high load?
Medium · Technical Domain & Modernization
Approach
- Separate signaling from media. Signaling (for example SIP) can scale horizontally behind load balancers, as long as every message for one call (same Call-ID) reaches the same node or the call state is shared. Media (RTP over UDP) is sensitive to latency and jitter, and media servers or session border controllers scale with concurrent sessions and transcoding CPU.
- Size capacity from busy-hour traffic, not daily averages. Offered load in Erlangs equals calls per hour times average holding time in hours, and Erlang B gives the channels needed for a target blocking probability. Cut transcoding load by negotiating a common codec end to end.
- Protect calls already in progress under overload. Use admission control that rejects new calls cleanly (SIP 503 with Retry-After) instead of letting every call degrade, and rate-limit registration storms after an outage.
- Remove single points of failure. Run active-active nodes across sites, use DNS SRV records (priority and weight) for failover, and decide explicitly whether calls in progress survive a node loss, which requires replicating call state, or only new calls fail over.
- Load test before peaks with a SIP traffic generator such as SIPp. Watch post-dial delay, answer-seizure ratio, jitter, packet loss and MOS, plus CPU per concurrent call, and mark voice packets for QoS (DSCP EF, value 46) so congestion elsewhere does not hit audio.
Follow-up
- How do you size for a known spike, such as an emergency or seasonal peak, without paying for that capacity all year?
- A media server dies with active calls on it. What happens to those calls, and what would it take to keep them up?
- Which single metric would you alert on first for call quality, and why?
How do you balance the trade-off between rapid feature delivery and long-term system maintainability?
Medium · Problem-Solving & Systems Thinking
Approach
- Frame it as a cost decision rather than a principle. Separate reversible choices (internal code structure, which can be cleaned up later) from hard-to-reverse ones (data models, public interfaces, security controls), and spend design effort on the second group even under deadline.
- Make the baseline non-negotiable and automatic. Tests, code review and pipeline gates (lint, unit tests, static security scanning, dependency checks) run on every change, so speed comes from small batches and feature flags rather than from skipping checks.
- When you take a shortcut on purpose, record it: a ticket with an owner, the cost it will cause (slower changes, incident risk), and a trigger for paying it back, such as the next feature that touches that module. Reserve a share of each iteration for repayment.
- Measure both sides together, for example with the four DORA metrics: deployment frequency and lead time for changes for speed, change failure rate and time to restore service for stability. If speed rises while the failure rate climbs, the balance is off.
- Close with a real example: a shortcut you chose, what it cost later, and how you repaid it. A story showing both outcomes is more credible than a rule.
Follow-up
- Give an example where choosing speed cost you later. What would you do differently?
- How do you get a stakeholder to fund a refactor that has no visible feature?
- Where would you refuse to cut corners even under a hard deadline?
When faced with competing priorities from different stakeholders, how do you determine which technical debt to
Medium · Problem-Solving & Systems Thinking
When faced with competing priorities from different stakeholders, how do you determine which technical debt to address first?
Approach
- Start with an inventory and agree on ranking criteria with stakeholders before debating individual items: impact (incidents, security exposure, time added to each change, upcoming work it blocks), likelihood, and effort. A cost-of-delay over job-size ratio (WSJF) is one way to turn that into an order.
- Put risk that is not optional at the top: known vulnerabilities in dependencies, runtimes or libraries past end of support, and anything with compliance exposure. Next comes debt on the hot path of the planned roadmap, which you can find by crossing code churn from version control with complexity and incident history.
- Back each claim with evidence stakeholders understand: hours lost per change in that module, pages and incidents traced to it, build or deploy time. Translate engineering pain into delivery risk and dates.
- Reduce the conflict by bundling repayment with feature work that already touches the same code, and name a decision owner for genuine ties instead of negotiating every item separately.
- Mention the debt nobody feels until it fails: knowledge held by one person, undocumented legacy jobs, missing tests around a fragile module. Explain how you would surface it so it gets ranked at all.
Follow-up
- Two stakeholders both insist their item comes first. Who makes the call, and how?
- How did you show afterwards that paying down that debt was worth it?
- Which debt would you deliberately leave alone, and why?
Tell us about a time you optimized a system that was underperforming. What metrics did you use to measure succ
Medium · Problem-Solving & Systems Thinking
Tell us about a time you optimized a system that was underperforming. What metrics did you use to measure success?
Approach
- Use STAR and open with a baseline: which metric was bad and by how much. Use latency percentiles (p50, p95, p99) rather than averages, plus throughput, error rate, resource utilization, cost, or for a batch job its end-to-end runtime against its window.
- Find the bottleneck before changing anything: traces from APM, database query plans (EXPLAIN ANALYZE), CPU profiles or flame graphs. Amdahl's law limits the gain: if a fraction p of the time speeds up by a factor s, the overall speedup is 1 / ((1 - p) + p / s).
- Name the fix and its trade-off. A missing index adds write cost and storage. Batching N+1 queries into a join or bulk fetch changes the shape of the code. A cache adds staleness and invalidation work. Connection pooling, async processing or a better algorithm each carry their own costs.
- Measure the result under comparable conditions: the same dataset, a load test, or a canary against a control. That rules out a quieter traffic week as the explanation, and checking the other metrics confirms nothing else regressed.
- Report the result as a number on the metric users feel (for example p99 latency before and after), then say what you would tackle next and what monitoring you left in place to catch a regression.
Follow-up
- How did you know the improvement came from your change and not from lower load?
- Why did you choose that percentile or metric as the success measure?
- What did the optimization cost in memory, complexity or data freshness, and was it worth it?
Explain your process for debugging a complex failure in a production-level environment.
Medium · Technical Domain & Modernization
Approach
- Mitigate before diagnosing. Gauge the impact (users, regions, data at risk) and restore service with the cheapest reversible action: roll back, turn off a feature flag, fail over or scale out. Then hunt for the root cause, with someone owning communication to stakeholders.
- Build a timeline. List what changed near the onset (deploys, configuration, dependency versions, certificate expiry, scheduled jobs, data volume) and line it up against when the metrics turned. Confirm the symptom is real and not a monitoring or logging fault.
- Narrow the scope. Check which hosts, regions, tenants or request types are affected, using rate/errors/duration dashboards for services, utilization/saturation/errors for resources, distributed traces and logs joined by request ID. Test first the hypothesis that splits the remaining possibilities in half.
- Reproduce with captured inputs in a lower environment. If it only happens in production, add targeted, low-risk instrumentation and change one variable at a time so each result is interpretable.
- Close the loop. Separate the trigger from the underlying cause, ship the fix with a regression test, and write a blameless postmortem with actions for detection (the alert that should have fired) as well as prevention.
Follow-up
- The failure will not reproduce outside production. What do you do next?
- How do you decide between rolling back and fixing forward?
- Describe a case where your first hypothesis was wrong. What evidence changed your mind?
Suggested practice checklist
Each day targets one cluster of the reported questions or one part of the stack candidates name, and ends with something written that you can reread before the interviews.
Day 1 — Map the loop and your own systems
- Write the two reported rounds, Initial Screening and Technical Evaluations, and the stack items in the posting: COBOL, Maximo, DevSecOps, CI/CD, Java or Python.
- Mark each stack item as used, adjacent or new, and write one honest sentence bridging each gap.
- Choose the two or three projects you will use for deep-dive answers and write the architecture and one failure for each.
Deliverable: A one-page map of the rounds and stack gaps, plus a project sheet with architecture, decisions and one failure per project.
Day 2 — Legacy modernization and legacy databases
- Outline a zero-downtime modernization of a legacy system: parallel run, traffic slicing, reconciliation checks and the rollback trigger.
- List the failure modes of a modern service reading a legacy database, and pair each with a mitigation such as an anti-corruption layer or contract tests.
- Say both answers aloud and cut anything that does not carry a decision.
Deliverable: A cutover outline and a table of legacy-database hazards with mitigations, each with a spoken version.
Day 3 — DevSecOps pipeline story
- Sketch a pipeline with secret scanning, static analysis, dependency scanning, image scanning and dynamic testing, and mark which stage blocks the build.
- Write the gate policy: severities that block, suppression ownership and expiry.
- Write your pipeline answer as a story with one measured result and one thing that went wrong.
Deliverable: A pipeline diagram with the blocking policy and a written story ready to speak.
Day 4 — Scalability and production debugging
- Take a voice or communication system and find its bottleneck on the call setup path and on the media path, then list what you would measure and shed first under load.
- Write your production debugging sequence: what changed, reproduction, bisection, fix, follow-up.
- Practise the dependency-conflict and critical-code-review scenarios as spoken walkthroughs.
Deliverable: A load-handling outline, a debugging checklist, and two scenario walkthroughs.
Day 5 — Trade-offs, debt and optimization
- Write a rule you use to balance delivery speed against maintainability, with one example where it changed a decision.
- Build a simple ranking for technical debt that weighs incident risk, change frequency and stakeholder impact, and test it on two items from your work.
- Prepare the optimization story with baseline, change and measured result.
Deliverable: A debt-ranking rubric and a metrics-backed optimization story.
Day 6 — Behavioral stories and the unknown system
- Write the troubleshooting-without-documentation story with the evidence you used and the artifact you left behind.
- Write the account of a failure and what you changed afterward, plus one example of explaining a system limit to a non-technical stakeholder.
Deliverable: Four written behavioral stories, each with a decision, a result and a lesson.
Day 7 — Full dry run
- Run a spoken mock covering the screening walk-through, then three technical questions chosen at random from the reported set.
- Review where you rambled or skipped the trade-off, and tighten those answers.
- Write the questions you will ask about the team's current challenges, location and clearance steps.
Deliverable: A recorded or timed mock with notes on weak answers and a final list of questions to ask.
Stories to prepare: pipelines, unknown systems, measured fixes
Candidates report prompts about DevSecOps experience, working without documentation and measuring an optimization, along with an emphasis on the reasons behind past architectural decisions and how you handled unexpected failures. Prepare stories where you made the call, with evidence and a result.
- Tell us about a time you optimized a system that was underperforming. What metrics did you use to measure success?
- Describe a failure on a system you owned and what you changed afterward.
- Tell me about a time you explained a technical limitation to a non-technical stakeholder.
Describe your experience with DevSecOps pipelines. How do you integrate security testing into an automated bui
Medium · Technical Domain & Modernization
Describe your experience with DevSecOps pipelines. How do you integrate security testing into an automated build process?
Approach
- Open with the pipeline you worked on in one or two sentences: language, build tool, where code is built and deployed. Then name what you personally added, not what the team had. If your experience is on Java or Python services rather than COBOL or mainframe builds, say so and describe how the same gates would carry over.
- Walk the pipeline left to right. Run secret scanning and linting before or at commit, static analysis and dependency (software composition) scanning on every pull request, container or image scanning at build, infrastructure-as-code checks before deploy, and dynamic testing against a staging environment. Sign or checksum the artifact so the thing tested is the thing deployed.
- Describe the gate policy, because it is the real decision. For example, fail the build on new high-severity findings, warn on lower ones, and require an expiry date and an owner on every suppression. Keep fast checks on the pull request and move slow scans to a nightly or pre-release stage so developers do not route around the pipeline.
- Close with a result you measured: findings caught before merge, a vulnerable dependency blocked or patched, change in build time, or a drop in false positives after tuning. Mention one thing that went wrong, such as a noisy rule that was ignored, and what you changed.
- The mistake that sinks this answer is a tool list with no decision in it. Pick one scan type, explain why it sits where it does, and show a case where it stopped something or was wrong.
Follow-up
- A scanner blocks a release on a finding you believe is a false positive. What do you do?
- How do you decide which findings block a build and which only warn?
- How would you add this to a build for a legacy codebase that has no automated tests?
Describe a time you had to troubleshoot an issue where you did not have access to the original documentation.
Medium · Problem-Solving & Systems Thinking
Describe a time you had to troubleshoot an issue where you did not have access to the original documentation. What was your strategy?
Approach
- Pick a story where the system was running in production or about to be changed, the original author and the documentation were unavailable, and you owned the outcome. Give the situation in two sentences and the stakes in one, then spend the rest on method.
- Show how you rebuilt understanding from evidence, in order: read the logs and configuration, trace the code path from the symptom, check version control history and ticket history for why code looks the way it does, and read the schema or message formats to see what data actually flows. Say which source you trusted least and why.
- Show how you stayed safe. Reproduce in a non-production copy, make read-only observations first, change one thing at a time, and have a rollback ready. Describe how you confirmed your model was right, for example by predicting what a log line or query result would show before looking, or by adding a characterization test that pins current behavior.
- Include the people side: who you asked, such as operators, support staff or former owners, and what you asked that the code could not tell you. End with the result and the artifact you left behind, such as a runbook, a diagram or tests, so the next person is not in the same position.
- The mistake that sinks it is a story that ends with 'I figured it out' and no method, or a hero narrative where you changed production on a hunch. Make the evidence and the safety steps visible.
Follow-up
- How did you verify your understanding was correct before you changed anything in production?
- What would you have done if nobody who knew the system could be reached?
- What did you leave behind so the next engineer would not start from zero?
Unblock an engineer without taking the keyboard
Easy · mentoring · leases · at-least-once
A teammate has spent two days on a job handler that occasionally writes duplicate rows. They are certain the queue is delivering twice by mistake. You suspect a lease expiring under a slow handler, so the job is running concurrently with itself. Describe how you have unblocked someone in this position: what you asked before offering a hypothesis, what you showed them rather than told them, and what you left them owning. Then say what you would do if their theory turned out to be the right one.
Approach
- Ask before diagnosing, and ask for things answerable from data they already have: the attempt count on the job rows that produced duplicates, the handler's observed duration against its lease expiry, and whether the duplicate rows share a natural key that a unique constraint could have caught.
- Teach the shape rather than the answer. A lease cannot distinguish a dead worker from a slow one, so a handler that outruns its lease is running twice by design, and deploys deliver the other half by killing handlers mid-run on every rollout. Both of their candidate theories produce identical duplicate rows, which is why the evidence has to come from timings rather than from argument.
- Hand over a checklist they execute: a natural key on every write the handler performs so the second copy collides rather than appends, the record of intent written before any external effect, a lease heartbeat while running, and the metric that shows it working.
- Keep ownership with them deliberately. Pair on the first write, then step back; if you finish it yourself you have closed one ticket and left the same person stuck on the next redelivery.
Follow-up
- How would you distinguish a genuine double-delivery from a lease expiry using only the data already stored?
- Their handler calls an external endpoint before recording that it did. What do you tell them to change first?