cswork / libraryOpen practice workspace

Interview guides · BBA inc.

BBA inc. Software Engineer Interview Guide

BBA inc. Software Engineer interview guide: four reported rounds, technical, architecture and behavioral questions candidates report, and a 7-day plan.

The 60-second brief

Candidates describe BBA inc. as a firm where engineering solutions meet industrial project management. The Software Engineer builds the internal software that mechanical and electrical engineers use in their work and that feeds client deliverables. Reported responsibilities include tools for data analysis, automating routine engineering calculations, and keeping digital workflows fast and secure. Candidates also describe the engineer owning the code from design through testing and deployment, and working close to the engineers who use it, so that software can remove bottlenecks in their workflows.

This guide is for engineers applying to BBA inc. as a Software Engineer, at the intermediate-to-senior range candidates describe. It covers the four reported rounds, the ten reported questions (technical performance and debugging, architecture and security, and behavioral collaboration), and a seven-day plan. questions.

Candidates report four rounds over roughly 3-5 weeks: Initial Screening, Technical Assessment, Behavioral Interviews and Final Interviews. The last stage is described as discussions with peer engineers and project leads.

Focus areas

  • Software Engineering (General)
  • Engineering Problem Solving
  • Software Development Lifecycle (SDLC)

Overview

The reported question list is made of open-ended prompts, not named algorithm puzzles. Four ask how you work technically: performance on large data sets, debugging a production failure, keeping code maintainable over multi-year projects, and integrating custom software with legacy industrial systems. Three are architectural: designing a system from scratch, balancing rapid delivery against technical debt, and system security and data integrity in an industrial context. Three are collaboration stories: explaining a technical concept to a non-technical stakeholder, disagreeing with a peer, and pivoting when requirements change. Preparing means having a concrete, first-person example behind every one of these.

The role context shapes which examples to pick. Candidates describe software used by mechanical and electrical engineers, with calculations, data analysis and workflow automation at its centre. An example in which wrong output has a real cost (a miscalculated value, a corrupted record, a stale import) is a better fit than a story about a consumer feature. The requirements candidates describe list modern programming languages, data structures, system design and teamwork. Nice-to-haves are industrial automation, hardware-software integration and experience in energy or infrastructure. If you have none of the nice-to-haves, say so plainly and lean on the closest constrained-environment work you have done.

Candidates are also advised not to rely only on theoretical algorithms and to explain how code behaves in a real, constrained environment. In practice, for each technical answer state your assumptions about data volume, memory, latency, units and failure modes, and say how you would measure the result. Practise saying why you chose an approach, since that reasoning is what the open-ended prompts leave room for.

Behavioral and final rounds are reported as conversations about teamwork and overall fit with peer engineers and project leads. Build a story bank of five or six projects, each with the decision you personally made, the alternatives you rejected, the people affected and the measurable result. Then map each story to several of the reported prompts so you are never improvising from nothing.

The BBA inc. interview process

These are the four stages candidates report, in the order they describe. Detailed formats are not reported, so the preparation below is built around the question types each stage covers.

Initial Screening

Candidates describe the Initial Screening as the opening stage, used to check your qualifications and fit for the role. No format, interviewer or question list is reported for it, so treat it as a conversation about your background. Approach it by lining your experience up against the requirements candidates describe: modern programming languages, data structures, system design and team-based work, plus the nice-to-haves of industrial automation, hardware-software integration and energy or infrastructure experience.

What to demonstrate

  • How your background lines up with the listed requirements, including data structures and system design experience
  • Whether your interest in software for engineering and industrial work is credible and specific
  • Your ability to summarise your own projects clearly

How to prepare

  • Write a short walk-through of your two most relevant projects, stressing who used the software, what you owned from design to deployment, and what changed because of it
  • List each must-have and nice-to-have requirement with your honest evidence, and note the closest substitute where you have a gap (for example constrained-environment or hardware-adjacent work)
  • Prepare two questions about the team's current technical challenges, which candidates are advised to ask

Technical Assessment

The Technical Assessment is reported as the stage that evaluates problem-solving skills and technical knowledge. Its exact format is not reported, so be ready for spoken technical discussion and for working through a problem live. The reported technical prompts concern performance on large data sets, debugging a complex production failure, long-term maintainability, legacy integration, technical debt, and security and data integrity in an industrial context. Treat each as a structure to rehearse: assumptions, diagnosis or design, trade-offs, how you would verify.

What to demonstrate

  • Problem-solving skills and technical knowledge, as the stage is described
  • Command of data structures and the reasoning behind your technical choices
  • How clearly you talk through a problem, including when you are stuck

How to prepare

  • Rehearse the reported technical questions aloud, each with stated assumptions, a measured approach and one trade-off you accepted
  • Write a production-debugging checklist: scope the symptom, find what changed, form a bisection, verify the fix, add a regression test

Behavioral Interviews

Candidates report Behavioral Interviews that look at cultural alignment and teamwork. The reported prompts are about explaining a technical concept to a non-technical stakeholder, disagreeing with a peer's technical recommendation, and pivoting a project when requirements change. The role works with mechanical and electrical engineers, so choose stories that involve people outside software. Use the STAR structure candidates are advised to use, and spend most of your time on the Action and Result.

What to demonstrate

  • Teamwork and collaboration across disciplines, as the stage is described
  • Communication with people who do not share your technical background
  • How you handle disagreement and changing requirements

How to prepare

  • Write five stories from your own work, each with the decision you personally made, the alternatives you rejected and a result you can state
  • Map every story to at least two of the reported collaboration prompts so one story can flex to different questions
  • Say each story aloud in STAR order and cut anything in Situation that is not needed to understand your Action

Final Interviews

The Final Interviews are described as in-depth discussions with peer engineers and project leads to judge overall fit. The interviewers are reported to be peers and leads, so expect questions that blend technical depth with how you would work on the team. Approach it as a discussion: be ready to go a level deeper on any project or answer you gave earlier, and bring questions about the team's own technical challenges.

What to demonstrate

  • Overall fit as judged in discussion with peer engineers and project leads
  • Depth on your own past projects, including design choices and trade-offs
  • Whether your answers across the earlier stages hold together

How to prepare

  • Pick two projects and prepare design-level detail on each: data volumes, failure modes, testing, deployment and what you would change
  • Rehearse the architecture prompts (design from scratch, technical debt versus delivery, security and data integrity) as conversations with a peer, not a monologue
  • Prepare questions about the team's current technical challenges and how engineers and the people who use the tools work together

Where candidates lose points

Answering the large-data-set performance question with a list of tricks (add an index, add a cache, use more threads) instead of a measured diagnosis

Start from what you would profile and measure, name the likely bottleneck (I/O, memory, a quadratic loop, a missing index), state the data volume you assume, and say how you would prove the fix worked.

Giving the production-debugging answer as a story of heroic fixing, with no sequence

Walk through scoping the symptom, checking what changed and when, bisecting, confirming the cause and not just the trigger, then the regression test and the write-up that stops it recurring.

Treating maintainability and technical debt as slogans (clean code, write tests, refactor often)

Give concrete practices tied to multi-year projects: tests around core calculations, documented units and assumptions, code review, deprecation paths, and a rule for when you pay debt down versus ship.

Ignoring the constrained, industrial setting in the security and integrity answer, or treating it as a purely theoretical exercise

State what must never be corrupted, then cover validation at every boundary, access control, audit trails, backups and a recovery path.

Telling collaboration stories entirely in the first person plural, or stories where the other party is a villain

Make your own decision explicit in each story, describe the other person's view fairly, and include an outcome and a lesson. Prepare stories that involve engineers from other disciplines, not just software peers.

Questions & practice

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

  1. 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.
  2. 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.
  3. 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.
  4. 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?

Merge partitioned event streams into one ordered feed with bounded lateness

Hard · k-way merge · watermarks · out-of-order streams

The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.

Approach

  1. Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
  2. Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
  3. Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
  4. Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.

Follow-up

  • The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
  • The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?

Find overlapping job attempts and peak concurrency from lease records

Medium · sweep line · intervals · leases

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

Approach

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

Follow-up

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

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?

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

  1. 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.
  2. 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.
  3. 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.
  4. 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 optimize software performance when interacting with large-scale data sets?

Medium · Technical Proficiency and Domain Knowled

Approach

  1. Measure before changing anything: set a target (p95 latency, throughput or peak memory), profile with a real tool (cProfile or py-spy for code, EXPLAIN ANALYZE for SQL) and say whether the bottleneck is CPU, I/O, memory or network, because each one has a different fix.
  2. Reduce the data you touch: push filters and aggregations into the database, select only the needed columns, and add indexes that match the WHERE, JOIN and ORDER BY columns (a composite B-tree index serves its leftmost prefix). Replace OFFSET paging with keyset paging, since OFFSET still reads and throws away every skipped row.
  3. Stream instead of loading everything: process in chunks or generators so memory is bounded by the chunk size, not by n. Batch writes (executemany, COPY, bulk insert) and remove N+1 query patterns that pay one round trip per row.
  4. Fix the algorithm before adding hardware: swap a nested-loop lookup, O(n*m), for a hash-map join, O(n+m); vectorise numeric work such as engineering calculations with NumPy; for analytical reads, use a columnar format like Parquet so a query reads only the columns it needs.
  5. Cache or precompute last (materialised views, precomputed aggregates), and name the cost: stale data and invalidation logic. Parallelise only after that, and check for lock or I/O contention that can cancel out the gain.

Follow-up

  • A query that was fast at one million rows is slow at a hundred million. How do you find out why, and what in the plan would you look at first?
  • The data set does not fit in memory. How would you compute a median or a distinct count? (External sort, or approximate sketches such as t-digest and HyperLogLog, and their error trade-off.)
  • How do you show that the optimisation helped and did not change any results?

What strategies do you use to ensure code maintainability across long-term, multi-year projects?

Medium · Technical Proficiency and Domain Knowled

Approach

  1. Draw clear module boundaries: keep domain logic (calculations, business rules) apart from I/O, persistence and UI, behind small interfaces, so each part can be tested and replaced on its own. Dependencies should point toward the core, never out of it.
  2. Make tests the safety net for future change: unit tests on pure logic, integration or contract tests at system boundaries, and regression tests pinned to known reference results. Run them all in CI on every merge.
  3. Let tools enforce consistency instead of memory: a formatter, a linter, static typing (mypy, TypeScript), required code review, and pinned dependencies in lockfiles with scheduled upgrades rather than one big jump years later.
  4. Record why, not just what: architecture decision records for major choices, a README and runbook per service, and comments only where the reason is not obvious. Docs kept next to the code go stale more slowly than a separate wiki.
  5. Manage change on purpose: semantic versioning and deprecation periods for shared libraries, feature flags for risky changes, and no premature abstraction (wait until the third repeat before generalising).

Follow-up

  • You inherit a ten-year-old codebase with no tests. Where do you start? (Characterisation tests around the area you must change, then strangler-fig replacement.)
  • How do you keep dependency upgrades from turning into a multi-month migration?
  • Which signal would tell you that maintainability is getting worse (lead time per change, change failure rate, churn in a few hotspot files)?

How do you balance the need for rapid feature delivery with the necessity of long-term technical debt manageme

Medium · Architectural Thinking

How do you balance the need for rapid feature delivery with the necessity of long-term technical debt management?

Approach

  1. Make the debt visible and priced: log each item with its 'interest' (how often it slows a change, the incidents it caused) and its cost to fix. Separate deliberate debt, taken to hit a date, from accidental debt found later.
  2. Decide with reversibility as the test: accept shortcuts that are local and easy to undo (a hard-coded config, a manual step), and refuse ones that are expensive to reverse: data integrity, security, schema and public interface design.
  3. Pay it down in a planned way: reserve a fixed share of each iteration, or refactor the code you are already changing for a feature, so cleanup lands where it pays off soonest instead of in a big-bang rewrite.
  4. When you take a shortcut on purpose, write down what was skipped, what will trigger the revisit, and who owns it, and put tests around it so the later refactor is safe.
  5. Explain the trade-off in delivery terms a project lead can weigh: lead time, defect and incident rate, and schedule risk on the next feature, rather than 'code quality'.

Follow-up

  • Name a shortcut you would refuse even under a hard deadline, and why.
  • How would you persuade a project manager to fund a refactor that ships no visible feature?
  • How would you measure whether debt is actually slowing the team down?

What is your approach to ensuring system security and data integrity in an industrial context?

Medium · Architectural Thinking

Approach

  1. Start with a threat model: the assets (control commands, measurement data, design files), the actors and the entry points. For plant-connected systems, segment the IT and operational networks into zones with controlled conduits between them (the IEC 62443 approach) so a compromised office host cannot reach control equipment.
  2. Apply least privilege everywhere: role-based access, narrowly scoped service accounts, MFA for people, secrets kept in a vault rather than in code, and read-only paths to control systems unless a write is truly needed.
  3. Protect data in transit and at rest: TLS between services and encryption at rest. Many legacy industrial protocols such as Modbus have no built-in authentication, so put them behind a gateway or VPN, or use OPC UA with signing and encryption turned on.
  4. Enforce integrity in layers: validate inputs (range, unit and timestamp checks on sensor values), use database constraints and transactions, hash files to detect tampering, keep append-only audit logs, and make writes idempotent so retries do not duplicate records.
  5. Plan for operations: equipment that cannot be patched often needs compensating controls, plus monitoring and anomaly alerts, backups proven by test restores, and an incident response runbook.

Follow-up

  • A legacy device only speaks an unauthenticated protocol and cannot be patched. How do you protect it?
  • How would you detect that a stored measurement was silently corrupted or altered?
  • A write has to update two systems consistently. How do you avoid partial updates? (Transactional outbox, idempotency keys, or a saga with compensating steps.)

Explain your process for debugging a complex system failure in a production environment.

Medium · Technical Proficiency and Domain Knowled

Approach

  1. Contain the damage first: measure the impact (which users, how many errors), then mitigate with a rollback, a feature-flag switch-off or a failover before hunting for the root cause, and keep stakeholders updated while you work.
  2. Build a timeline: what changed and when (deploys, config, dependency versions, data volume, infrastructure), lined up against when the metrics turned. Scope the failure by comparing affected and unaffected hosts, regions or inputs.
  3. Locate the failing component with observability: error rate, latency and saturation metrics, logs joined by a request or correlation ID, and distributed traces. Check that the instrumentation is right before you believe a symptom (a missing metric can look like zero traffic).
  4. Test hypotheses one at a time with steps that rule something out whichever way they go: git bisect across commits, toggle a single flag, replay the failing input in staging with production-like data. Keep the trigger (a traffic spike) separate from the cause (an undersized connection pool).
  5. Close the loop: fix the cause, add a regression test and an alert that would have caught it earlier, and write a blameless postmortem with owned action items.

Follow-up

  • The failure is intermittent and you cannot reproduce it locally. What do you do next? (Suspect races or resource exhaustion, add targeted logging, raise trace sampling, capture a thread or heap dump.)
  • How do you choose between rolling back and pushing a forward fix?
  • What would you add so this class of failure is detected sooner next time?

Suggested practice checklist

The plan starts with your story bank and role fit, then works through the reported technical and architecture questions, then the collaboration prompts, and ends with a full rehearsal for the final discussions. questions.

Day 1 — Map the loop and build your story bank

  • Write the four reported rounds (Initial Screening, Technical Assessment, Behavioral Interviews, Final Interviews) and, for each, the question types you expect it to cover.
  • List the listed requirements and nice-to-haves with your own evidence for each, and mark any gaps.
  • List five or six projects as story seeds, each with your decision, the people affected and a result.

Deliverable: A one-page loop map, a requirements-versus-evidence table and a list of five or six story seeds.

Day 2 — Large data sets and performance

  • Answer the large-data-set performance question aloud with stated assumptions, a measurement plan and the likely bottlenecks.
  • Write down which of your own projects had a measurable performance problem and what you measured.

Deliverable: A spoken answer to the performance question, worked solutions to the two drills and one real performance story.

Day 3 — Production debugging and maintainability

  • Write your production-debugging checklist and apply it aloud to one real failure you have handled.
  • Answer the multi-year maintainability question with at least four concrete practices and one example of each.

Deliverable: A debugging checklist with one worked example, a list of maintainability practices with examples and a solved drill with tests.

Day 4 — Architecture, technical debt, security and data integrity

  • Answer the question on rapid delivery versus long-term technical debt with a rule you actually follow for deciding when to pay debt down.
  • Outline an answer on security and data integrity for an industrial system: validation, access control, audit trail, backups and recovery.

Deliverable: A debt-versus-delivery rule, a one-page security and integrity outline and two solved drills with notes.

Day 5 — Legacy integration and a system built from scratch

  • Write the legacy-integration story in STAR order: the constraint, the adapter, how you tested safely, how you cut over and the result.
  • Write the design-from-scratch story with the two or three decisions, the options rejected and the criterion for each.
  • Say both aloud and cut each to the essentials.

Deliverable: Two polished STAR stories, each with named trade-offs and a result.

Day 6 — Communication, disagreement and changing requirements

  • Write the story of explaining a technical concept to a non-technical stakeholder, including the analogy or example you used.
  • Write the peer-disagreement story, covering both positions, the evidence you used and the outcome.
  • Write the pivot story: what changed, what you kept, how you communicated the new scope.

Deliverable: Three STAR stories with the other person's perspective and a result in each.

Day 7 — Full rehearsal for the final discussions

  • Run a full mock: answer one technical, one architecture and one behavioral prompt back to back, speaking to a friend or a recording.
  • Pick two projects and prepare design-level follow-ups: data volumes, failure modes, testing and what you would change.
  • Write your questions about the team's current technical challenges and how engineers and tool users work together.

Deliverable: A recorded mock with notes on weak spots, two projects prepared in depth and a list of questions to ask.

Stories for engineers who build tools for other engineers

The reported behavioral stage looks at teamwork and cultural alignment, and the final stage is described as discussions with peer engineers and project leads. For this role that means stories about working with people outside software, such as mechanical and electrical engineers, and about making technical decisions you can defend. Reported prompts come first below, followed by extra prompts for the legacy, ownership and constrained-environment themes.

  1. Tell me about software you owned from design through testing and deployment, and what you would change about it.

How do you handle integration challenges between custom software and legacy industrial systems?

Medium · Technical Proficiency and Domain Knowled

Approach

  1. Choose a story where you personally did the integration. Name the legacy side concretely (a file export, a database view, a vendor protocol, a scheduled batch) and what you could not change about it. The constraint is the heart of the story.
  2. Describe the isolation you built: an adapter or translation layer so the custom software never depended directly on the legacy format, with explicit handling of units, encodings, time zones, missing values and versioned formats.
  3. Explain how you tested without risking the live system: captured real sample data as fixtures, wrote tests that pin the legacy system's current behaviour, then ran the new path in parallel or read-only before cutting over.
  4. Cover failure handling: validation at the boundary, alerts when the legacy side sends something unexpected, a rollback path, and documentation of the quirks so the knowledge does not sit in one head.
  5. Close with a result you can state (hours of manual re-entry removed, error rate, outage avoided) and one thing you would redo. Avoid the story that amounts to "I rewrote it all", which ignores the constraint.

Follow-up

  • What would you do if the legacy system's owner refused to change anything on their side?
  • How did you verify the integrated output matched what the old process produced?
  • What happens to your integration when the legacy system changes its format without warning?

Describe a time you had to design a system from scratch. What were your primary trade-offs?

Medium · Architectural Thinking

Approach

  1. Pick a system you designed and carried to production, and say how large your own share was. State the problem, the users (ideally engineers or analysts) and the hard constraints in two or three sentences.
  2. Name the two or three real decision points, such as build versus buy, monolith versus separate services, a relational store versus a simpler file-based one, synchronous versus queued processing, or flexibility versus time to ship. For each, say the options you weighed and the criterion that decided it.
  3. Show that you sized the problem: expected data volume, number of users, what must never be wrong, and what could be eventually consistent. Trade-offs without numbers sound like opinions.
  4. Say what you did to keep the design testable and modular so it could evolve, and what you deliberately left out for later.
  5. Finish with what happened: what held up, which decision you would reverse, and how you found out. An honest reversal is stronger than a design that went perfectly.

Follow-up

  • Which decision turned out to be wrong, and what did it cost to change?
  • How would the design change at ten times the data or users?
  • How did you validate the design with the people who would use it before you built it?

Tell me about a time you had to explain a highly technical concept to a non-technical stakeholder.

Medium · Behavioral and Collaborative Problem-Sol

Approach

  1. Pick a concrete concept that mattered to a decision, such as why a result carries an error margin, why a migration needed a freeze, or why a data feed could not be trusted yet. A story with a decision at the end is stronger than one that only shows you can simplify.
  2. Open with who the stakeholder was (for example a project manager or an engineer from another discipline) and what they needed to decide. Build the explanation backwards from that decision, not from your own mental model.
  3. Describe the tools you used: an analogy from their own field, a small example with real numbers, or a diagram. Say what you deliberately left out and what you refused to oversimplify.
  4. Show how you checked understanding, for instance by asking them to restate the trade-off or by seeing whether their decision followed. Then state the outcome and any follow-up documentation you wrote.
  5. Avoid the version where the stakeholder is portrayed as slow and you as the patient expert. Describe what you learned about their constraints.

Follow-up

  • How did you know they had really understood and were not just agreeing?
  • What did you do when they pushed back because of a deadline?
  • Which part did you choose not to explain, and why was that safe?

How do you handle a situation where you disagree with a peer’s technical recommendation?

Medium · Behavioral and Collaborative Problem-Sol

Approach

  1. Choose a real technical disagreement with a peer about a recommendation, such as a data model, a library, an approach to testing or a release plan, where both positions were reasonable. State the peer's position fairly, in terms they would accept.
  2. Explain how you moved the discussion from opinion to evidence: agreed the criteria first (correctness, performance, maintenance cost, delivery date), then ran a small benchmark, spike or prototype, or looked at past incidents.
  3. Show how you handled it as a relationship: you talked privately before any group setting, asked questions to understand their constraints, and involved a lead only if the two of you were deadlocked.
  4. State the outcome whichever way it went. If you were wrong, say what changed your mind. If you disagreed and still committed, show that you supported the decision fully.
  5. The mistake that sinks this answer is a story where you win by escalating or by being right while the peer is the villain.

Follow-up

  • What would you have done if the evidence had been inconclusive?
  • Tell me about a time a peer changed your mind. What convinced you?
  • How would you handle it if the peer were more senior than you?

Describe a challenging project where you had to pivot your strategy due to changing requirements.

Medium · Behavioral and Collaborative Problem-Sol

Approach

  1. Pick a project where a real change forced a re-plan, such as a changed regulation, a new client requirement, a different data source or a shift in what the users needed. Say what changed, who told you and how early you found out.
  2. Show your decision process: what you salvaged, what you threw away and how you avoided the sunk-cost trap. Mention design choices (modular boundaries, configuration over hard-coding, tests) that made the pivot cheaper, or the lack of them.
  3. Describe how you re-planned and communicated: the new scope, what slipped, what the stakeholders were asked to accept, and how you kept the team aligned.
  4. Give a result and a lesson, for example that you now confirm which requirements are most likely to move and keep those parts isolated.
  5. Avoid blaming the person who changed the requirements. A story about adapting is stronger than one about being wronged.

Follow-up

  • How did you decide what to discard and what to keep?
  • What would you do earlier next time to see the change coming?
  • How did you explain the delay or scope change to the people waiting on the work?