cswork / libraryOpen practice workspace

Interview guides · Armtec Defense Technologies

Armtec Defense Technologies Software Engineer Interview Guide

Armtec Defense Technologies Software Engineer interview guide: five reported rounds, coding, system design and behavioral questions, with a 7-day plan.

The 60-second brief

Armtec Defense Technologies is described as a company that builds software for national defense work. Candidates report project areas such as simulation systems, data analytics platforms and embedded systems, with algorithms for allocating resources and operator-facing user interfaces named as examples. The Software Engineer role is reported to sit alongside hardware engineers, project managers and defense analysts, so the work includes integrating software with hardware, reviewing teammates' code, and testing and debugging continuously.

This guide is for Software Engineer candidates, and the experience level candidates describe is roughly two to five years in software development. It covers the five reported rounds, the coding, design, debugging and behavioral questions candidates report, and a week of preparation built around them. The languages and tools listed for the role are C++, Python or Java, Git, JIRA and Agile practice.

Candidates report five rounds over roughly four to six weeks: Initial Screening, Interviews with Managers, Technical Assessments, Behavioral Questions and System Design Discussions. A mix of virtual and in-person sessions is described, with coding possible during technical conversations.

Focus areas

  • ISO auditing
  • Lean manufacturing
  • Six Sigma (DMAIC)

Overview

The reported questions fall into five groups: explaining past work and technical fundamentals, system design, behavioral and leadership questions, problem-solving case studies, and coding. The coding group is classic computer science material: reversing a linked list, implementing a cache, solving a problem with dynamic programming, stating and improving time complexity, and comparing depth-first with breadth-first search. These are answerable in any of the three listed languages (C++, Python or Java), so pick one before you start practising and stay in it.

The design group is broad rather than tied to one product. Candidates report questions on designing for high availability, the trade-offs between microservices and a monolith, API design factors, and storage for a large-scale application. Because the role is described as working next to hardware engineers and on embedded and simulation software, it also helps to be ready to say how your design choices change when a component cannot be redeployed quickly or must keep running when a dependency fails.

A large share of the list is behavioral: leading a team through a difficult project, handling conflict, mentoring, prioritizing across projects, a failed project, a last-minute requirement change, and why you want to work in the defense technology sector. The same few real stories can answer most of these if you pick them well, so the plan has you build a small set of stories first and then test each against several prompts.

Several questions ask you to walk through your own work: a complex project and its technologies, how you debug, how you use version control, how you write unit tests, and a performance refactor. These are the questions where vague answers are easiest to spot, so prepare them with specifics from your own repositories: the commands, the tools and the numbers you actually measured.

The Armtec Defense Technologies interview process

Candidates describe the stages below in this order. Which questions appear in which stage is not reported, so prepare each question type for any stage that fits its format.

Initial Screening

Candidates report that the first stage is a recruiter screen that checks general fit for the role. Nothing more specific is reported about its content, so treat it as a conversation about your background, the languages you work in and your reasons for applying to a defense-sector employer. Approach it as the first time you say your project story and your motivation aloud.

What to demonstrate

  • Fit for the role as a recruiter sees it
  • How clearly you summarise your experience with C++, Python or Java
  • Whether your background lines up with the two to five years of development experience candidates describe

How to prepare

  • Write a two-minute walk through your career that names your main language, your use of Git and JIRA, and one project you can go deep on.
  • Decide in advance how you will explain your interest in the defense technology sector, using the motivation prompt in the behavioral section.
  • Prepare questions about the team, whether it works on simulation, analytics or embedded software, and what the later rounds contain.

Interviews with Managers

Candidates report interviews with hiring managers and technical leads, aimed at technical capability. The reported question types that fit this format are explaining a complex project and its technologies, describing how you debug, naming design patterns and when to use them, version control habits, and what matters when writing unit tests. Answer from real work, because follow-ups naturally dig into the details you choose.

What to demonstrate

  • Technical capability as shown through your own projects
  • Command of everyday engineering practice: debugging, testing, version control
  • Ability to explain technical choices clearly to a manager and a lead

How to prepare

  • Pick one project and outline architecture, your contribution, the hardest bug, and what you would change; practise it aloud.
  • Write a short debugging routine (reproduce, bisect, read logs, form and test a hypothesis) and attach a real bug you fixed to each step.
  • List four design patterns you have actually used, each with the concrete problem it solved and a case where it was the wrong choice.

Technical Assessments

Candidates report a mix of technical assessments that includes coding challenges. The reported coding questions are linked list reversal, building a cache, a dynamic programming problem, complexity analysis with ideas for improving it, and depth-first against breadth-first search. A coding stage tests working code, so practise writing and testing solutions in your chosen language rather than only discussing them.

What to demonstrate

  • Working code for classic data structure and algorithm problems
  • Ability to state time and space complexity and improve a first solution
  • Clear explanation of the reasoning while coding

How to prepare

  • Write iterative linked list reversal with prev, current and next pointers, then the recursive version, and test it on empty, one-node and two-node lists.
  • Implement an LRU cache with a hash map plus a doubly linked list, or the standard library equivalent, with O(1) get and put.
  • Solve two dynamic programming problems end to end, writing the state definition and recurrence before any code, and give the complexity of each.

Behavioral Questions

Candidates report a behavioral stage that checks cultural fit and collaboration. The reported prompts include leading a team through a difficult project, handling team conflict, mentoring someone, prioritizing across several projects, analyzing a failed project and explaining your motivation for defense technology. Build each answer from a real situation where you personally made a decision.

What to demonstrate

  • Collaboration and communication in a team setting
  • Leadership and mentoring experience, even without a management title
  • How you reason about conflict, priorities and failure

How to prepare

  • Write six stories in a few lines each (a difficult project, a conflict, a mentoring case, a failure, a performance refactor, a prioritization call) and map each to at least two prompts.
  • For every story, record your own decision, the result you can state in numbers or a concrete outcome, and what you would change.
  • Rehearse the defense-sector motivation answer aloud until it sounds like your own reasoning, not a slogan.

System Design Discussions

Candidates report system design discussions as the final stage. The reported topics are high availability, microservices against a monolith, factors in API design, and data storage for a large-scale application, so expect broad architecture reasoning rather than one fixed product. Work through each from requirements to components to failure modes, and say which trade-off you are choosing and why.

What to demonstrate

  • Problem-solving across an open-ended architecture question
  • Awareness of availability, consistency and failure behavior
  • Reasoned trade-offs rather than a single memorised design

How to prepare

  • Practise a repeatable outline: requirements and scale, API, data model, components, failure modes, then bottlenecks and trade-offs.
  • For high availability, write down redundancy, health checks, failover, replication and what happens during a partial outage.
  • Prepare one storage comparison (relational against key-value or document) with the access pattern that would make you choose each.

Where candidates lose points

Reversing a linked list but losing the rest of the list or missing edge cases

Save the next node before changing the pointer and move prev and current forward each step. Test an empty list, a single node and two nodes, then state O(n) time and O(1) extra space for the iterative version.

Describing depth-first and breadth-first search without tying them to data structures or use cases

Say that depth-first uses a stack or recursion and breadth-first uses a queue. Add that breadth-first finds shortest paths in unweighted graphs, that both run in O(V+E), and that depth-first depth can cause stack overflow on deep inputs.

Implementing a cache as a bare hash map with no eviction, size limit or complexity story

Name the eviction policy first, then build it: a hash map plus a doubly linked list gives O(1) get and put for LRU. Mention expiry, thread safety and what happens on a miss.

Answering the high availability, API and storage design questions with a component list and no failure behavior

Start from requirements, then say what happens when a node, a dependency or a network link fails. Cover redundancy, failover, replication, data consistency, and the trade-off you are choosing for the use case.

Telling behavioral stories in the plural, without your own decision or an outcome

For every story, write the decision you made, the alternative you rejected, and a concrete result or lesson. The failed project and the defense-sector motivation answers need the same personal detail as the leadership one.

Questions & practice

Write a function that reverses a linked list.

Medium · Coding / Algorithms

Approach

  1. Confirm the contract: a singly linked list, reverse in place, return the new head; the empty list and a single node must work unchanged.
  2. Iterative solution with three pointers: prev = null, curr = head; loop while curr: next = curr.next, curr.next = prev, prev = curr, curr = next; return prev. O(n) time, O(1) extra space.
  3. Recursive alternative: reverse the rest, then head.next.next = head and head.next = null. Also O(n) time, but O(n) stack, so a long list can overflow the stack (CPython's default recursion limit is 1000).
  4. Test empty, one node, two nodes, and odd and even lengths; walk the result to confirm the order and that the old head's next is null (no cycle). In C++ with raw pointers no allocation is needed; with unique_ptr nodes, move ownership carefully.
  5. Know the variants: reverse positions m to n in one pass, reverse in groups of k, and for a doubly linked list swap prev and next on every node.

Follow-up

  • Reverse only the nodes between positions m and n in one pass.
  • Reverse the list in groups of k nodes.
  • Check whether a linked list is a palindrome using O(1) extra space.

How would you implement a caching mechanism?

Medium · Coding / Algorithms

Approach

  1. Clarify requirements: what is cached, the size bound, eviction policy, how stale data may be, read/write ratio and whether it is accessed concurrently.
  2. LRU in O(1): a hash map from key to node plus a doubly linked list in recency order; get moves the node to the front, put inserts at the front and evicts from the tail when over capacity. Library shortcuts: Python OrderedDict with move_to_end and popitem(last=False), or Java LinkedHashMap with accessOrder = true and an overridden removeEldestEntry.
  3. Compare policies and write modes: LFU (O(1) with frequency buckets), TTL expiry, cache-aside versus write-through versus write-back, and how writes invalidate entries.
  4. Concurrency: get changes recency, so even reads mutate shared state; start with one mutex around the map and list, then shard into independently locked segments if contention shows up.
  5. For a shared cache (Redis, Memcached): invalidate by deleting on write, prevent stampedes on hot-key expiry with request coalescing or jittered TTLs, and decide what happens when the cache is down.

Follow-up

  • Make the cache thread-safe without one global lock becoming the bottleneck.
  • Add a per-entry expiry time. How do expired entries get removed?
  • How do you stop a stampede of database requests when a hot key expires?

Solve a problem using dynamic programming and explain your thought process.

Medium · Coding / Algorithms

Approach

  1. Pick a concrete problem and state it, for example minimum coins to make an amount. Start from the brute-force recursion and point out the overlapping subproblems and optimal substructure that make DP apply.
  2. Define the state precisely, then the recurrence and base cases: dp[0] = 0, dp[a] = min over coins c <= a of dp[a - c] + 1, with unreachable amounts kept at infinity and reported as -1. O(amount x coins) time, O(amount) space.
  3. Choose top-down memoisation (closest to the recursion, only visits reachable states) or bottom-up tabulation (no recursion depth, easy to reduce memory), and state the evaluation order.
  4. Reduce memory where possible: a 1-D array for knapsack, iterating capacity downward for 0/1 items and upward for unbounded items; two rows for longest common subsequence.
  5. Reconstruct the answer by storing the choice made at each state, and check the table by hand on a tiny input before claiming it works.

Follow-up

  • Return which coins were used, not just how many.
  • Why does greedy fail for coins {1, 3, 4} and amount 6?
  • Reduce the memory of the longest common subsequence table to O(min(m, n)) for the length.

What is the time complexity of your solution, and how could it be improved?

Medium · Coding / Algorithms

Approach

  1. Count the dominant work: nested loops multiply, and recursion gets a recurrence (T(n) = 2T(n/2) + O(n) gives O(n log n) by the master theorem). Report space separately, including the recursion stack.
  2. Look for hidden costs: membership tests on a list are O(n) against O(1) average for a hash set, Python list.pop(0) is O(n) where collections.deque.popleft is O(1), and Java String += in a loop is O(n^2) overall where StringBuilder avoids it.
  3. Name the levers for improving it: a better data structure (hash map, heap with O(log n) operations, sorting plus binary search), precomputation such as prefix sums, two pointers or a sliding window, memoisation, early exit.
  4. Distinguish worst, average and amortised cases: dynamic array append is amortised O(1), hash lookups degrade to O(n) under heavy collisions, quicksort is O(n^2) in the worst case.
  5. Know when to stop: comparison sorting has an Omega(n log n) lower bound; and on small inputs or constrained hardware, constants and cache locality can beat a better asymptotic bound.

Follow-up

  • What is the space complexity, counting the recursion stack?
  • Can you show that no comparison-based approach does better?
  • Why is appending to a dynamic array amortised O(1)?

Explain the difference between depth-first and breadth-first search algorithms.

Medium · Coding / Algorithms

Approach

  1. BFS uses a FIFO queue and explores level by level, so it finds the path with the fewest edges in an unweighted graph; its memory grows with the width of the frontier.
  2. DFS uses a stack (explicit or the call stack) and goes deep first; memory grows with depth. It is the natural fit for cycle detection, topological sort, connected components, path existence and backtracking.
  3. Both run in O(V + E) with an adjacency list and O(V^2) with an adjacency matrix. Track visited nodes on graphs with cycles, and in BFS mark a node when it is enqueued so it is not queued twice.
  4. Know the limits: BFS is not correct for weighted shortest paths (use Dijkstra for non-negative weights, or 0-1 BFS with a deque for weights 0 and 1); iterative deepening DFS gives BFS's shallowest-first result with DFS's memory.
  5. On very deep graphs, recursive DFS can overflow the stack, so I write it iteratively with an explicit stack.

Follow-up

  • Find the shortest path through a grid with obstacles.
  • Detect a cycle in a directed graph.
  • Which uses less memory on a wide, shallow tree, and which on a deep, narrow one?

Replace offset paging on the resource feed with keyset

Easy · keyset pagination · composite index · sort order

resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.

Approach

  1. Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
  2. Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
  3. Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
  4. Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.

Follow-up

  • The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
  • Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?

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 a complex project you worked on and the technologies you used.

Medium · Technical / Domain Questions

Approach

  1. Pick one project where I owned a component, and open with one sentence on what the system did, who used it, and the constraint that made it hard (memory on a target board, data volume, latency or reliability).
  2. Sketch the architecture as 3-5 boxes (inputs, processing, storage, interfaces) and name each technology at the box where it runs, with the alternative I rejected and why (for example C++ for deterministic memory on the device, Python for test tooling).
  3. Spend most of the answer on one hard technical decision: the options, the trade-off, and the measurement or test result that settled it.
  4. Keep my part distinct from the team's ('I wrote the parser and its tests; another engineer owned the UI') and close with outcomes I can defend in numbers plus what I would change now.

Follow-up

  • Why that language or framework instead of the alternative you mentioned?
  • What broke after release, and how did you find the cause?
  • If you rebuilt it today, what is the first thing you would change?

What design patterns are you familiar with, and when would you use them?

Medium · Technical / Domain Questions

Approach

  1. Organise the answer by the Gang of Four families: creational (Factory Method, Builder, Singleton), structural (Adapter, Decorator, Facade) and behavioral (Strategy, Observer, State, Command).
  2. Give each pattern I name a concrete problem: Strategy to swap an algorithm at runtime behind one interface, Observer to publish state changes to several subscribers, Adapter to wrap a vendor or legacy API, State to replace a growing switch on operating mode, Builder for objects with many optional parameters.
  3. Name the costs: extra indirection and more classes. Singleton is hidden global state that makes tests order-dependent and complicates concurrency, so I usually inject the dependency instead.
  4. Show language awareness: in Python a first-class function often replaces Strategy or Command; in C++ RAII handles resource lifetime and templates (including CRTP) give static polymorphism without virtual-call overhead.
  5. State the rule I follow: introduce a pattern when the second real variation appears, not in anticipation of one.

Follow-up

  • What is the difference between Decorator and Adapter?
  • Why is Singleton often called an anti-pattern, and what would you use instead?
  • How would you implement Observer so that one slow subscriber cannot block the publisher?

What are the most important considerations when writing unit tests?

Medium · Technical / Domain Questions

Approach

  1. Test behaviour through the public interface, not private implementation details; one behaviour per test, Arrange-Act-Assert structure, and names that say the scenario and expected result.
  2. Keep tests fast and deterministic: inject the clock, randomness, filesystem, network and hardware access so they can be faked; seed any RNG; no dependence on test order or shared state.
  3. Choose cases systematically: the normal path, boundaries (empty, single element, maximum, off-by-one), invalid input and error paths, equivalence partitions; use property-based testing (Hypothesis, RapidCheck) for invariants such as round-trip encode and decode.
  4. Treat coverage as a signal, not a goal: line coverage does not show the assertions are meaningful, branch coverage and mutation testing do better, and safety standards such as DO-178C require MC/DC coverage at their highest level.
  5. Avoid over-mocking, which couples tests to implementation and lets real integration bugs through; run the suite in CI on every change and fix or quarantine flaky tests right away.

Follow-up

  • How do you unit test code that reads the current time or a hardware register?
  • When can a mock hide a real bug?
  • What is the difference between a stub, a mock and a fake?

How would you design a system to handle high availability?

Medium · System Design / Architecture

Approach

  1. Set the target first: an availability goal (99.9% allows about 8.8 hours of downtime a year, 99.99% about 53 minutes), recovery time and recovery point objectives, and which failures are in scope: process, host, zone or region.
  2. Remove single points of failure: stateless replicas behind a load balancer with health checks, spread across failure domains, with N+1 capacity so losing one node still serves peak load.
  3. Handle state explicitly: synchronous replication gives zero data loss at a write-latency cost, asynchronous replication can lose recent writes on failover; automate failover with quorum-based leader election (Raft, etcd, ZooKeeper) and fencing to prevent split brain.
  4. Contain dependency failures: timeouts, retries with exponential backoff and jitter, idempotent operations, circuit breakers, bulkheads and graceful degradation; note that dependencies in series multiply, so three 99.9% services give about 99.7%.
  5. Verify it works: SLO-based alerting, canary or rolling deploys with fast rollback, regular failover drills, and backups whose restore is actually tested.

Follow-up

  • How do you prevent two nodes from both acting as primary during a network partition?
  • What changes if the system must keep operating while disconnected from any central service?
  • Which part of your design would you test first with a failure drill, and how?

Discuss the trade-offs between microservices and monolithic architectures.

Medium · System Design / Architecture

Approach

  1. Monolith strengths: one deployable, in-process calls, ACID transactions in one database, simple local development and debugging. Costs: every change redeploys everything, scaling is all-or-nothing, and coupling grows unless module boundaries are enforced.
  2. Microservice strengths: independent deploys and scaling per service, fault isolation, team autonomy, freedom to pick a stack per service. Costs: network latency and partial failure, versioned contracts, eventual consistency, distributed tracing and much more operational work.
  3. Cross-service consistency needs patterns instead of a single transaction: sagas with compensating actions, the transactional outbox, and idempotent consumers.
  4. Decide on drivers: number of teams (Conway's law), parts with different scaling or release needs, and whether domain boundaries are understood yet. My default is a modular monolith, extracting services along bounded contexts once one needs independent scaling or deployment.
  5. Call out the worst outcome: a distributed monolith, where services share one database or must be deployed in lockstep, so you pay both sets of costs.

Follow-up

  • How would you split an existing monolith without a big-bang rewrite?
  • How do you keep two services consistent when one write must update both?
  • How would you trace a slow request that crosses five services?

What factors do you consider when designing APIs?

Medium · System Design / Architecture

Approach

  1. Start from the consumers and their use cases, then model resources and operations with correct HTTP semantics: GET is safe, PUT and DELETE are idempotent, POST is not. Use precise status codes (400, 404, 409, 422, 429, 503) and one consistent error body.
  2. Write the contract down (OpenAPI or protobuf) with consistent naming, explicit units and time zones, and cursor or keyset pagination instead of offset for large, changing collections.
  3. Plan for evolution: additive changes only, never repurpose a field, a clear versioning scheme, and a deprecation path with usage tracking.
  4. Design for unreliable networks: idempotency keys so clients can retry creates safely, optimistic concurrency with ETag and If-Match, timeouts and rate limits.
  5. Security and protocol choice: authentication plus per-resource authorisation, strict input validation, no internal details in errors; REST for broad client reach, gRPC for typed low-latency service-to-service calls and streaming, a message queue when the caller should not wait.

Follow-up

  • How would you make a create endpoint safe for a client to retry after a timeout?
  • How do you change a field's type without breaking existing clients?
  • When would you choose gRPC or a message queue over REST?

Explain how you would approach data storage for a large-scale application.

Medium · System Design / Architecture

Approach

  1. Start from requirements: entities and access patterns (point lookups, range scans, aggregates, full text), read/write ratio, data volume and growth, latency targets, consistency needs and retention.
  2. Match the store to the access pattern: a relational database for transactions and joins, key-value or wide-column stores for high-volume keyed writes, object storage for large blobs, a time-series database for telemetry, a search index for text, a columnar warehouse for analytics.
  3. Scale reads with indexes, caching and read replicas (and handle replica lag where a user must read their own write); scale writes by partitioning on a key that spreads load evenly, noting that cross-partition queries and hot keys become the expensive cases.
  4. State the consistency trade-off: under a partition you choose consistency or availability; with replication factor N, choosing read and write quorums where R + W > N makes every read overlap the latest acknowledged write.
  5. Cover operations: backups with tested restores, online schema migrations, tiering or expiring cold data, encryption at rest and in transit, and access control with audit logs.

Follow-up

  • How do you choose a partition key, and what do you do about a hot key?
  • How would you change the schema of a very large table without downtime?
  • Where would you store high-rate telemetry versus configuration data, and why?

You have a limited budget for a project. How would you allocate resources efficiently?

Medium · Problem-Solving / Case Studies

Approach

  1. Clarify the objective and constraints first: what counts as value (requirements that must be met, user outcomes), which items are mandatory, the deadline, and whether the budget is money, people-weeks or hardware.
  2. Estimate cost and value per work item and fund the mandatory items first. The rest is a 0/1 knapsack: ranking by value per cost is a reasonable heuristic but not guaranteed optimal for whole items, while dynamic programming solves it exactly in O(n x B) for integer budgets.
  3. Spend early on the riskiest unknowns (a prototype or spike on integration or performance) so later estimates firm up, and hold back a contingency for what the spike reveals.
  4. Compare build, buy and reuse for each component; cut scope before cutting testing or reliability work, because those costs come back later.
  5. Track spend against plan at each milestone, re-plan when estimates move, and record the trade-offs in writing for the stakeholders who own the decision.

Follow-up

  • Two must-have features together exceed the budget. What do you do?
  • How do you estimate work your team has never done before?
  • Which item would you cut last, and why?

How would you handle a last-minute change in project requirements?

Medium · Problem-Solving / Case Studies

Approach

  1. Clarify the change before reacting: what exactly is changing, why, who asked, and the date it is needed. Get it in writing so it can be traced.
  2. Run an impact analysis: which modules, interfaces, tests and documents it touches, which other teams or hardware interfaces depend on them, and an estimate with its uncertainty.
  3. Present options with trade-offs and let the owner choose: absorb it by cutting named scope, move the date, or ship in phases behind a feature flag.
  4. Implement safely: update or add tests that encode the new requirement first, keep the change isolated in a branch, run the full regression suite, and keep requirement-to-test traceability current.
  5. Afterwards, review why the change arrived late and whether the design should absorb this kind of change more cheaply (configuration, cleaner interfaces).

Follow-up

  • What if the stakeholder will not move the date or cut scope?
  • How do you stop repeated late changes from degrading the codebase?
  • Tell me about a time you pushed back on a requirement change.

Describe a complex problem you faced in a project and how you solved it.

Medium · Problem-Solving / Case Studies

Approach

  1. Pick a problem whose cause was not obvious, such as a race condition, memory leak, performance cliff or hardware-software integration mismatch, and where I did the diagnosis myself.
  2. Structure it: context in two sentences, the symptom with numbers, the hypotheses I considered and the evidence that ruled each out, then the root cause.
  3. Name the exact tools and techniques (profiler, tracing, logic analyzer, git bisect, a minimal repro) so every step can be checked.
  4. Explain the fix and why I chose it over the alternatives, including the trade-off it introduced.
  5. Finish with the measured result and the prevention I added (a regression test, monitoring, a design change), keeping my contribution distinct from the team's.

Follow-up

  • Which hypothesis were you most confident in that turned out wrong?
  • How could this have been caught earlier?
  • What trade-off did your fix introduce?

What steps would you take to ensure your solution meets user needs?

Medium · Problem-Solving / Case Studies

Approach

  1. Identify the users and their operating context (operators, analysts, other engineers) and observe or interview them doing the real task rather than relying only on a written spec.
  2. Turn needs into testable acceptance criteria and use cases, including non-functional ones: response time, reliability, usability under real conditions, security.
  3. Validate early and often: mockups or prototypes before heavy build, short iterations, and a demo to real users at the end of each one.
  4. Keep traceability from each requirement to design and to a test, and automate acceptance tests where possible so regressions surface.
  5. After release, measure task completion, error rates and field reports, and feed them back into the backlog.

Follow-up

  • What do you do when the end users and the people funding the system want different things?
  • How do you validate needs when you cannot reach end users directly?
  • How would you write a testable acceptance criterion for a usability requirement?

Analyze a failed project experience and discuss what you learned.

Medium · Problem-Solving / Case Studies

Approach

  1. Choose a real failure with consequences (missed delivery, cancelled feature, outage) in which I played a part, not a success dressed up as a failure.
  2. Analyse it like a blameless postmortem: timeline, contributing factors (unclear requirements, late integration, untested assumptions, technical debt), and a few rounds of 'why' to reach the root cause.
  3. Separate what was in my control from what was not, and own my part in specific terms.
  4. Turn lessons into concrete practice changes and show evidence I applied them later, for example integrating with hardware or other teams earlier, or keeping a risk list reviewed every iteration.
  5. The answer fails if it blames others or ends with a vague lesson such as 'communicate more'.

Follow-up

  • What early warning sign did you miss?
  • What did you do differently on the next project, and did it work?
  • How did you tell stakeholders about the failure?

How do you approach debugging a piece of software?

Medium · Technical / Domain Questions

Approach

  1. Reproduce first: capture the exact input, build version, configuration and environment, and shrink it to the smallest deterministic repro. If it is intermittent, suspect timing, concurrency or uninitialised memory and collect logs or core dumps before touching code.
  2. Narrow the search space: diff what changed, use git bisect between a known-good and known-bad commit (about log2(n) test runs for n commits), and binary-search the input or code path with assertions at module boundaries.
  3. Test one hypothesis at a time with a prediction: breakpoints and watchpoints in gdb or pdb, targeted logging, and for C++ memory or threading faults AddressSanitizer, UndefinedBehaviorSanitizer, ThreadSanitizer or Valgrind.
  4. Fix the root cause rather than the symptom: write a regression test that fails before the fix and passes after, then search the codebase for the same pattern.
  5. For timing-sensitive bugs, remember that extra logging or a debugger can hide the bug; prefer timestamped trace buffers or record-and-replay tools such as rr.

Follow-up

  • How would you debug a crash that happens only on the target hardware and never on your workstation?
  • A failure shows up about once a week in production. What do you do first?
  • How do you prove the fix addressed the cause and not just the trigger?

Suggested practice checklist

The plan starts with coding fundamentals, moves to project and debugging answers, then system design, and finishes with behavioral stories, following the order of the reported rounds in reverse of difficulty to retain.

Day 1 — Map the loop and inventory your stories

  • Write the five reported rounds on one page and note which question types fit each one, marking the one you are least ready for.
  • Pick one language from C++, Python or Java for coding practice and set up a test file where you can run solutions.
  • List six real work situations (a hard project, a conflict, a mentoring case, a failure, a performance fix, a tight-deadline call) in a line each.

Deliverable: A one-page loop map with your weakest round marked, a runnable practice file, and a list of six candidate stories.

Day 2 — Linked lists, graph search and complexity

  • Write iterative and recursive linked list reversal and test the empty, one-node and two-node cases.
  • Write depth-first search (recursive and with an explicit stack) and breadth-first search on a graph, and note time and space for each.
  • For both solutions, write the time and space complexity and one way to improve or constrain it.

Deliverable: Tested reversal and traversal code, plus a written complexity statement and improvement for each solution.

Day 3 — Caching and dynamic programming

  • Implement an LRU cache with O(1) get and put and test eviction, update of an existing key and capacity of one.
  • Solve one dynamic programming problem by first writing the state and recurrence, then a memoized version and a tabulated version.
  • Write a short explanation of your DP thought process in the sequence you would say it aloud.

Deliverable: A working cache with tests, a DP solution in both forms, and a spoken-order explanation of the DP reasoning.

Day 4 — Project walkthrough, debugging, patterns and tests

  • Outline a complex project: goal, architecture, technologies, your contribution, hardest problem and result, and rehearse it aloud.
  • Write your debugging routine as numbered steps and attach a real bug from your history to it.
  • Prepare notes on four design patterns you have used and on what a good unit test covers (isolation, determinism, edge cases, readable failure).

Deliverable: A rehearsed project walkthrough, a numbered debugging routine with an example, and notes on patterns and unit tests.

Day 5 — System design: availability, services, APIs, storage

  • Design a highly available service on paper: components, redundancy, failover, data replication and what happens when each part fails.
  • Write a microservices against monolith comparison with the team size, deployment and consistency conditions that favor each.
  • List the API design factors you would check (resource naming, versioning, error handling, idempotency, authentication, pagination) and a storage choice for a large-scale application with the access pattern behind it.

Deliverable: Three annotated design sketches or outlines: a high availability design, a service architecture comparison, and an API plus storage design.

Day 6 — Behavioral stories, part one

  • Write full answers for the version control question, the performance refactor and the team leadership story, with your decision, an outcome and a lesson in each.
  • Write the conflict answer with both sides described fairly and the evidence that resolved it.
  • Record yourself giving each answer aloud and cut anything that is about the team rather than you.

Deliverable: Four written and recorded behavioral answers, each with a personal decision and a stated outcome.

Day 7 — Behavioral stories, part two, and mixed rehearsal

  • Write the answers on motivation for defense technology, mentoring and prioritizing across projects.
  • Prepare the failed project analysis, the last-minute requirement change response and the limited budget allocation answer.
  • Run a mock session: one coding question, one design question and three behavioral questions, spoken aloud.

Deliverable: Written answers for the remaining prompts and a recorded mock session with a list of weak spots to fix.

Behavioral and leadership preparation

Candidates report a behavioral stage and a manager stage, and the reported prompts cover leadership, conflict, mentoring, prioritization, a performance refactor, version control habits and your reasons for choosing defense technology. For this role the stories need to show collaboration with other disciplines and sound engineering decisions, each told with your own choice and a result.

Describe your experience with version control systems and how you manage code changes.

Medium · Technical / Domain Questions

Approach

  1. Describe a workflow you actually used: feature branches off a main branch, small focused commits, pull requests with review, and a rule for how branches are merged. Say whether you rebase to keep history linear or merge to preserve it, and why your team chose that.
  2. Show how changes are traced: commit messages or branch names that reference the JIRA ticket, tags for releases, and a way to find which commit introduced a regression, such as git bisect.
  3. Cover mistakes and recovery: resolving a merge conflict by understanding both sides rather than picking one, using git revert on a shared branch instead of rewriting history, and git reflog to recover lost work.
  4. Mention practices that keep changes reviewable: small pull requests, automated tests on each push, and keeping generated files and large binaries out of the repository or in a separate mechanism.

Follow-up

  • When do you merge, rebase or squash, and what does each do to history?
  • A bad commit has reached the shared main branch. How do you undo it without disrupting others?
  • How do you keep a long-lived branch from diverging badly?

Describe a time when you had to refactor a system for better performance.

Medium · System Design / Architecture

Approach

  1. Open with the measured problem: the symptom, the baseline number, and how you obtained it with a profiler or timing, such as latency percentiles or CPU time. Without a baseline the story reads as guesswork.
  2. Explain how you located the cause (a hot loop, repeated queries, needless copying, lock contention) and why you chose a refactor rather than a local fix.
  3. Describe how you kept behavior safe: tests written around the existing code first, small steps, review, and a comparison of outputs before and after, plus any rollout precaution.
  4. Report the result with the same measurement as the baseline, and name the cost you accepted, such as more memory, a more complex cache or code that is harder to read.
  5. Say what you learned about when not to optimise, for example leaving cold code alone.

Follow-up

  • How did you know the part you changed was the bottleneck?
  • What did you give up in exchange for the speedup?
  • How would you prevent the same regression from returning?

Describe a situation where you had to lead a team through a difficult project.

Medium · Behavioral / Leadership

Approach

  1. Choose a project where the difficulty was real (unclear requirements, slipping schedule, integration problems, a team member leaving) and where you held responsibility for direction, with or without a formal title.
  2. Show specific leadership actions: you split the work into owners and milestones, set up a regular check-in, surfaced risks early to the project manager, and removed blockers for teammates.
  3. Include how you communicated across roles, for example agreeing interfaces with a hardware or systems counterpart or updating a stakeholder when the plan changed.
  4. State the outcome plainly, including what slipped or was cut, and what you would do differently. Use I for your decisions and name the teammates who did their parts.

Follow-up

  • How did you handle a team member who was falling behind?
  • What did you decide to cut, and who agreed with that?
  • What would you change about how you planned it?

How do you handle conflicts within a team?

Medium · Behavioral / Leadership

Approach

  1. Pick a real disagreement, ideally technical (an approach, an interface, a review comment), and describe both positions fairly so the other person does not come across as a villain.
  2. Show your process: you listened and restated their concern, then moved the discussion from opinions to evidence, such as a small benchmark, a prototype or a written comparison of options.
  3. Say how it was settled: agreement from the data, a decision by the person who owned the area, or a compromise, and how you committed to the outcome even if it was not yours.
  4. End with the relationship afterwards and one habit you kept, such as raising concerns in the design review rather than in the pull request.

Follow-up

  • What if the other person still disagreed after the evidence?
  • Tell me about a time you were the one who turned out to be wrong.
  • How do you handle a conflict with someone more senior?

What motivates you to work in the defense technology sector?

Medium · Behavioral / Leadership

Approach

  1. Give a specific, honest reason rather than a general slogan. Connect it to the kind of work candidates describe for this role, such as simulation, data analytics, embedded systems or hardware-software integration, and to what you find satisfying about software whose reliability matters.
  2. Back the motivation with evidence from your history: a project where correctness, safety or dependability mattered, or work that pulled you toward this area.
  3. Show that you have considered the downsides, such as restrictions on what you can discuss about your work and the seriousness of how the software is used, and why you are comfortable with them.
  4. Keep it about the work you want to do. Avoid claiming detailed knowledge of the company's programs that you cannot support, and do not read like a rehearsed statement.

Follow-up

  • How would you feel if a project you worked on did not match your personal views?
  • What would you want to learn in your first year in this sector?
  • Why this field rather than a commercial software company?

Give an example of how you have mentored someone in your previous roles.

Medium · Behavioral / Leadership

Approach

  1. Choose a mentoring case with a clear starting gap, such as a junior engineer who struggled with debugging, reviews or design, and say what you noticed and how you agreed on goals with them.
  2. Describe what you did: pair programming sessions, code review comments that explained the reasoning, stretch tasks sized so they could succeed, and regular check-ins.
  3. Show progress with a concrete change in their work, such as owning a feature or shipping unaided, and credit the mentee for their effort.
  4. Cover one thing that went less well and what you adjusted, for example moving from giving answers to asking guiding questions. Mentoring that amounts to answering questions on request is a weak story.

Follow-up

  • How did you give difficult feedback?
  • What did you do when they didn't improve as quickly as you hoped?
  • What did you learn from the experience?

How do you prioritize your tasks when working on multiple projects?

Medium · Behavioral / Leadership

Approach

  1. Describe a concrete situation with competing demands, not a generic method. Name the tasks, their deadlines and who was waiting on each.
  2. State your criteria: user or mission impact, deadline and cost of delay, blocking others, effort, and risk. Say how you ranked the work and put it on a visible board such as JIRA so others could see the order.
  3. Show that you communicated: you told stakeholders what would slip and checked the order with whoever owned the priorities, rather than quietly deciding alone.
  4. Explain how you re-planned when something changed, and give the result, including what you deferred or declined.

Follow-up

  • Two managers both say their task is the top priority. What do you do?
  • What do you drop when everything is urgent?
  • How do you protect time for testing and review?