Interview guides · Calspan JETS
Calspan JETS Software Engineer Interview Guide
Calspan JETS Software Engineer interview guide: six reported rounds, C/C++ and Linux hardware questions, behavioral prompts and a 7-day prep plan.
The 60-second brief
Calspan JETS, as candidates describe it, works on the Data Acquisition and Control System (DACS), a Linux-based system used in ground-based jet engine testing. The data it captures is reported to go to airlines, engine manufacturers and maintenance, repair and overhaul businesses. A Software Engineer there develops and maintains that system, tunes its performance, brings new measurement hardware into it, tracks down bottlenecks, and is expected to guide other engineers on the team.
This guide is for experienced software engineers preparing for the Calspan JETS Software Engineer loop. Candidates describe requirements of 7+ years of programming or equivalent, C, C++ or Python, Linux development, and the ability to read wiring diagrams and mechanical drawings. Jet engine testing, LabVIEW or similar instrumentation software, and Jira or Confluence are listed as extras. The guide walks through each reported round, gives answer structures for all ten reported questions, and ends with a seven-day plan.
Candidates report six stages over about 4-6 weeks: Application Review, Screening Call, Panel Interview, Technical Deep Dive, Take-Home Assignment and Final Discussion. The take-home is described as something candidates may be asked to do, followed by a presentation or code walkthrough, and some candidates report an offer within 3 to 4 weeks.
Focus areas
- Data Acquisition and Control System (DACS)
- Linux
- Software Architecture
Overview
The work behind this loop is a Linux data acquisition and control system that reads from physical measurement hardware. That shapes the reported questions: five are about technical experience (optimizing Linux software for real-time or near-real-time use, integrating with measurement hardware, C or C++ for hardware interfacing, debugging when the fault could be software or hardware, and using Bash, Make or CMake) and five are about people and judgment (mentoring, deadline pressure, working with non-software engineers, motivation for aerospace testing, and speed versus reliability). Prepare both halves with equal weight, because candidates describe a panel that mixes technical skills and cultural fit.
Candidates describe the technical portion as average in difficulty and centred on your own experience and reasoning rather than algorithm puzzles. So the preparation is not a problem-set grind. It is being able to take one or two real projects and explain the signal path from sensor to stored data, the language and architecture choices behind it, how you measured performance, and how you isolated a fault. Every answer should carry a why, and a number or observation that proves you were there.
Candidates also report that the culture questions are organised around three named values: inclusive, accountable and innovative. Build one story per value, then check that your mentoring, deadline and cross-discipline stories can double as evidence for them. The requirements are written for people with substantial experience, and candidates mention mentorship stories for senior applicants, so have at least one example where you grew another engineer rather than only shipped your own code.
Finally, plan for the take-home. Reports say it may be followed by a presentation or code walkthrough, so treat it as two deliverables: code that builds cleanly from a fresh checkout with Make or CMake, and a short explanation of the decisions in it.
The Calspan JETS interview process
These are the stages candidates report, in the order they describe them; not every candidate sees every stage, and the take-home in particular is described as optional in some loops.
Application Review
Candidates describe this first stage as a review of your application for qualifications and fit. Nothing is asked live, so the preparation happens on paper: the requirements candidates describe name C, C++ or Python, Linux development, and reading wiring diagrams and mechanical drawings, with jet engine testing, LabVIEW-style instrumentation software and Atlassian tools as extras.
What to demonstrate
- How your listed experience lines up with the reported requirements: C/C++ or Python, Linux, and hardware-facing work
- Whether your CV shows ownership and, for senior applicants, mentoring
How to prepare
- Rewrite your CV so each role names the hardware or data source your software touched, the language used, and one measurable result
- Build a two-column table of the reported requirements against a project of yours that proves each one, and mark honest gaps such as LabVIEW or jet engine testing
Screening Call
Candidates describe a preliminary conversation to gauge interest and discuss the role. Treat it as a short, spoken version of your CV that is anchored to the DACS work: Linux-based data acquisition software, measurement hardware, performance troubleshooting.
What to demonstrate
- Whether your background matches the Linux, C/C++ and measurement-hardware profile of the role
- How clearly you explain your own projects and your reasons for wanting aerospace testing work
How to prepare
- Rehearse a spoken walkthrough of your most hardware-adjacent project, from sensor or instrument to stored data, naming the language, OS and interface you used
- Prepare your answer to why aerospace testing infrastructure, tied to something you have actually built, plus any questions you have about shifts or on-site expectations, which candidates mention can vary by role
Panel Interview
Candidates describe a detailed discussion with several interviewers that covers technical skills and cultural fit in the same sitting. Expect to switch between questions about Linux, C/C++ and your build workflow with Bash, Make or CMake, and stories about mentoring and working with colleagues from other disciplines.
What to demonstrate
- Technical experience in Linux and C/C++ explained to a mixed audience
- Cultural fit as candidates report it: being inclusive, accountable and innovative
- Whether your technical decisions come with reasons
How to prepare
- Prepare one story per reported value (inclusive, accountable, innovative) and check each also answers the mentoring, cross-discipline or deadline prompts
- Write out the Bash, Make or CMake setup from a real project: targets, variables, how builds are made repeatable, and what a new teammate runs first
- Practise explaining a hardware-facing design to someone who is not a software engineer without losing the technical detail
Technical Deep Dive
Candidates describe in-depth technical discussions about problem-solving and technical knowledge. Given the reported focus on experience rather than puzzle questions, the useful preparation is a well-structured account of systems you have built, tuned and debugged, especially performance work on Linux and fault isolation between software and hardware.
What to demonstrate
- Problem-solving method on a performance bottleneck or an ambiguous fault
- Depth of knowledge in Linux and C/C++ system-level work
- Understanding of how software behaviour maps to physical measurement hardware
How to prepare
- Prepare one performance story with a baseline, the tool or log that exposed the bottleneck, the change, and the measured result after
- Write your isolation sequence for a fault that could be software or hardware: reproduce, check known-good hardware, loopback or simulated input, compare timestamps and logs, then narrow
- Be ready to describe a system architecture of yours and defend the trade-offs, including how you documented it
Take-Home Assignment
Candidates say a take-home project may be required, and that it can be followed by a presentation or code walkthrough. No task details are reported, so prepare the general shape: a small, reviewable piece of work plus the ability to talk through it.
What to demonstrate
- Working, reviewable code that someone else can build and run
- Clear communication of requirements, assumptions and decisions during the presentation or walkthrough
How to prepare
- Set up a skeleton ahead of time: a Makefile or CMakeLists, a build and test script in Bash, a README with run steps and stated assumptions
- Practise walking a reviewer through your code in order of data flow, and say aloud what you would verify next on real hardware
- Keep a short list of design decisions with the alternative you rejected and why, so the walkthrough has reasons rather than only code
Final Discussion
Candidates describe a concluding conversation about the offer and any remaining questions. Candidates also mention that some roles involve different shifts or specific on-site requirements, so this is the place to settle practical expectations.
What to demonstrate
- Whether your expectations for role, schedule and location line up with the position
- The quality of the questions you ask about the team and the DACS work
How to prepare
- Write four questions about the DACS codebase, how hardware changes are tested before release, how documentation is kept in Confluence-style tools, and how mentoring works on the team
- Decide your position on shifts and on-site work before the call so the answer is calm and specific
Where candidates lose points
Describing hardware work only from the software side, with no mention of the sensor, signal, units or wiring
Before the loop, write the full path for one project: physical quantity, instrument, interface, driver, your code, timestamp, storage. Learn enough to answer how you checked a reading was correct.
Answering the software-or-hardware debugging question with a list of tools but no way of telling the two apart
Prepare an isolation sequence you have really used: reproduce, swap in known-good hardware or a loopback, compare timestamps and logs across the boundary, change one thing at a time, and state what each result rules out.
Telling a mentoring story in which you fixed the junior engineer's code or just described being approachable
Pick one person and one gap. Show the method (pairing, review with reasons, a graduated task), what you left to them, and the evidence they improved.
Treating speed versus reliability as a slogan and answering that you do both
Give a risk-tiering rule and one real trade-off: what you cut, what checks you kept, and what happened after.
Handing in a take-home that runs on your machine only, or presenting it as code with no reasons
Make it build from a clean checkout with Make or CMake, add a README, and keep a list of decisions and rejected alternatives so the walkthrough explains why.
Questions & practice
Track a rolling failure rate per destination for circuit decisions
Easy · sliding window · ring buffer · circuit breaker
The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.
Approach
- Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
- Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
- State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
- Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.
Follow-up
- The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
- A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?
Archive a resource graph without breaking live references or recursing
Medium · graph traversal · topological order · tenant isolation
Resources reference other resources within a tenant; for the largest tenant the reference table holds up to 2,000,000 nodes and 8,000,000 edges. Archiving a resource must archive everything reachable from it that nothing outside the set still references, refuse when a live external referrer exists, and terminate when references form cycles, which they legitimately do. Produce the archive order and the refusal list, targeting O(V+E). Say what stops the traversal crossing a tenant boundary, and why recursion is the wrong control structure at this size.
Approach
- Load the subgraph with the tenant predicate on both endpoints of the edge, not only on the side you started from. Scoping the left table alone is the classic cross-tenant leak: one mis-entered edge then pulls another tenant's resources into the traversal and, worse, into the archive.
- Traverse iteratively with an explicit stack. A 2,000,000-node graph can hold a chain deep enough to exhaust a native stack in the low tens of thousands of frames, and that failure is a process crash rather than an error you can return.
- Treat cycles as data rather than corruption: compute strongly connected components with Tarjan in O(V+E) using its own explicit stack, then condense. The condensation is a DAG, so a topological order over it gives the archive order, and every member of a component archives in one transaction because no order within a cycle is valid.
- Decide refusals with reverse edges. A candidate is archivable only if every in-edge originates inside the candidate set, so build the transpose or count in-degrees restricted to the visited set, and emit each blocked resource with the id of the external referrer, which is the only part of the answer an operator can act on.
Follow-up
- The graph is read in one query and the archive writes a minute later. What can change in between, and how do you make the write safe?
- The candidate set is 400,000 resources. Is that one transaction, and if not, what does a half-finished archive look like to a reader?
Identify the heaviest tenants in a five-minute window under memory pressure
Medium · top-k · heavy hitters · streaming
The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.
Approach
- Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
- Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
- State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
- Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.
Follow-up
- The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
- Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?
Find version gaps and relay lag with window functions
Medium · window functions · event tables · frame semantics
outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.
Approach
- Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
- Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
- Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
- Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.
Follow-up
- Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
- Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?
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
- 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.
- 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.
- 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.
- 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?
How have you optimized Linux-based software for performance in real-time or near-real-time environments?
Medium · Technical and Domain Proficiency
Approach
- Start from measurement, not tuning. Define the deadline (sample period, maximum allowed jitter), then measure worst-case latency with a histogram rather than an average: cyclictest for the platform, and perf or ftrace (trace-cmd) for your own process. A tail of rare 5 ms stalls matters more than a fast mean.
- Scheduling: put the acquisition thread on SCHED_FIFO with sched_setscheduler or pthread_setschedparam (this needs CAP_SYS_NICE or an RLIMIT_RTPRIO allowance), pin it with sched_setaffinity, and keep other load and IRQs off that core with isolcpus and /proc/irq/*/smp_affinity. Mention that a PREEMPT_RT kernel narrows worst-case latency, while stock Linux remains soft real-time.
- Memory: call mlockall(MCL_CURRENT | MCL_FUTURE) and prefault buffers so page faults cannot land in the hot path; preallocate everything at startup and never call malloc, printf or blocking syscalls inside the sampling loop.
- Decouple acquisition from slow consumers: the real-time thread writes samples into a preallocated single-producer/single-consumer ring buffer, and a normal-priority thread drains it to disk or network. Any lock shared with a lower-priority thread uses a PTHREAD_PRIO_INHERIT mutex to avoid priority inversion.
- Edge cases to name: a full ring buffer (count and flag dropped samples with sequence numbers instead of blocking), timestamps from CLOCK_MONOTONIC rather than wall-clock time, and the kernel's RT throttling default (sched_rt_runtime_us of 950000 per 1000000), which can stall a runaway FIFO thread.
Follow-up
- How did you prove the change reduced worst-case latency and not just average latency?
- What happens to data integrity when the consumer thread falls behind and the ring buffer fills?
- When would you move the time-critical part out of Linux userspace altogether, into a kernel driver, an FPGA or a microcontroller?
Explain how you utilize Bash, Make, or CMake to manage your development workflow.
Medium · Technical and Domain Proficiency
Approach
- Make: explain targets, prerequisites and recipes, and that Make rebuilds a target when a prerequisite's timestamp is newer. Mark non-file targets such as clean and test as .PHONY, generate header dependencies with gcc -MMD -MP and include the .d files so a header change triggers a rebuild, and run parallel builds with make -j.
- CMake: it generates the build system (Makefiles or Ninja) rather than building directly. Use out-of-source builds (cmake -S . -B build), target-based commands (target_include_directories, target_link_libraries with PUBLIC, PRIVATE or INTERFACE to control what propagates to dependents), find_package for libraries, and CMAKE_BUILD_TYPE for Debug or Release with single-config generators.
- Cross-compiling and testing: a toolchain file (CMAKE_TOOLCHAIN_FILE) selects the cross compiler and sysroot for a target board, and enable_testing with add_test lets ctest run unit tests in the same build. Export compile_commands.json (CMAKE_EXPORT_COMPILE_COMMANDS) for editors and static analysis.
- Bash: keep scripts for environment setup, deployment to a test machine and log collection. Start them with set -euo pipefail, quote every expansion ("$var"), use trap for cleanup, and run shellcheck. Know the caveat that set -e does not stop on a failing command inside an if condition or before && / ||.
- Trade-off to state: a hand-written Makefile is fine for a small single-platform tool; CMake earns its overhead once there are several targets, third-party libraries, multiple compilers or cross-compilation. Give a concrete example from your own workflow, such as one command that builds, tests and packages the same way locally and in CI.
Follow-up
- You edit a header and the binary does not change after make. What is wrong and how do you fix it?
- What is the difference between PUBLIC and PRIVATE in target_link_libraries, and what breaks if you pick the wrong one?
- How would you make the build reproducible across developer machines and a CI server?
How do you approach debugging a system when the issue could be either software or hardware-related?
Medium · Technical and Domain Proficiency
Approach
- Characterise before theorising: is the fault constant or intermittent, on one channel or all, tied to a software release, a firmware or kernel update, a cable change, temperature, vibration or load? Write down what changed and when, because that list sets the first split.
- Bisect at the software-hardware boundary: capture the raw values at the driver or bus level (raw ADC counts, frames on the serial or network link) and compare them with what the application shows. If the raw data is already wrong, the problem sits upstream of your code; if it is right, look at scaling, calibration tables, parsing or timing in your software.
- Use known references to isolate each half: inject a known signal from a calibrator or signal generator, or use a loopback, to test the hardware path; run a known-good software build on the same rig, and the suspect build on a known-good unit or channel. Each swap rules out one side whatever its result.
- Linux-side evidence: dmesg or journalctl for driver resets, buffer overruns and USB disconnects; strace for syscalls that time out or return errors; timestamped logging rather than breakpoints, since stopping a process changes timing and can hide the fault. Hardware-side evidence: a multimeter, oscilloscope or logic analyzer on the bus, checked against the wiring diagram.
- Close the loop: confirm the fix by reproducing the original failure and showing it gone, then leave something permanent behind, such as a self-test, range or sanity checks on incoming data, or extra diagnostic logging, so the next occurrence is quicker to classify.
Follow-up
- The fault appears only during a live test run and never on the bench. How do you gather evidence without disturbing the run?
- How would you convince a hardware engineer that the problem is on their side, or accept that it is on yours?
- A channel shows noisy readings: how do you tell electrical noise or a ground loop from a software sampling or scaling bug?
Suggested practice checklist
The plan starts with your CV against the reported requirements, then covers the hardware and Linux technical questions, the build-workflow and take-home skills, and the behavioral prompts, ending with a full dry run.
Day 1 — Map the loop and match your CV to the requirements
- Write the six reported rounds in order and one line on what you must have ready for each; mark the take-home as optional.
- Build a table of the reported requirements (C, C++ or Python, Linux, reading wiring diagrams and mechanical drawings, plus LabVIEW, jet engine testing and Atlassian tools as extras) against a project of yours that proves each one.
- Mark each gap and write the nearest experience you would offer in its place.
Deliverable: A one-page loop map and a requirements-to-evidence table with gaps marked.
Day 2 — Hardware integration and C/C++ interfacing stories
- Draw the signal path of your best hardware-facing project, from physical quantity to stored data, labelling where scaling and timestamps were applied.
- Write the structured answer for integrating software with physical measurement hardware, including how you validated the readings.
- Write the C/C++ interfacing answer: device, interface, byte-order and error handling, resource management, and the bug you learned from.
Deliverable: A signal-path diagram and two spoken-length written answers, one for each hardware question.
Day 3 — Linux performance and software-or-hardware debugging
- Write a performance story for Linux-based software in real-time or near-real-time use: baseline, the tool or log that found the bottleneck, the change, the result.
- Write your isolation sequence for a fault that could be software or hardware, with what each step rules out.
Deliverable: A one-page performance story, a one-page debugging runbook, and two solved drills.
Day 4 — Build workflow and a take-home skeleton
- Create a small C++ project with both a Makefile and a CMakeLists, and a Bash script that builds, runs tests and reports the result.
- Write a README that gives run steps, assumptions and limits, and rehearse explaining each build target aloud.
- List three design decisions in the project with the alternative you rejected.
Deliverable: A repository that builds from a clean checkout with one command, plus a decisions list for a walkthrough.
Day 5 — Mentoring and cross-discipline collaboration
- Write the mentoring story with the junior engineer's gap, your method, what you left to them and the evidence of growth.
- Write the collaboration story with a hardware or mechanical colleague, including a disagreement settled by measurement and the document you left behind.
- Tag each story with the value it best supports: inclusive, accountable or innovative.
Deliverable: Two written stories, each tagged with a reported value.
Day 6 — Pressure, reliability and motivation
- Write the deadline story with what you cut, what you protected and how you communicated risk.
- Write the speed-versus-reliability answer with your risk-tiering rule and one real trade-off.
- Write your motivation for aerospace testing infrastructure in your own words, tied to one project, and say it aloud until it sounds natural.
Deliverable: Three answers, written and spoken, including a motivation statement that cites one of your own projects.
Day 7 — Full dry run and questions for the final discussion
- Run a mock that mixes technical and behavioral questions and a ten-minute-style walkthrough of your day-4 repository, then note where your answers lost the why.
- Write four questions about DACS, hardware testing practice, documentation and mentoring, and decide your stance on shifts and on-site work.
Deliverable: A recorded mock with revision notes, and a list of four questions plus your logistics answer.
Stories from the test bench
Candidates report that the culture questions revolve around three named values (inclusive, accountable and innovative) and that the people questions concern mentoring, working with non-software engineers, deadline pressure and balancing speed with reliability. Prepare stories where your own decision and its effect on a physical or high-stakes system are visible, and where you can name the evidence.
Can you describe a time you had to integrate software with physical measurement hardware?
Medium · Technical and Domain Proficiency
Approach
- Choose a project where you wrote the integration yourself. Name the physical quantity, the instrument or sensor, how the host connected to it, and the sample rate you needed.
- Walk the signal path in order: hardware, interface, driver or vendor library, your acquisition code, timestamping, storage. Say where units, scaling and calibration were applied and who owned each step.
- Show how you proved the data was right: compared against a reference reading, checked a known input, looked for dropped or duplicated samples, reviewed the wiring or channel map with the hardware engineer.
- Cover what you did when the hardware misbehaved (disconnects, noise, timeouts) and how you tested without the rig, with a simulator or recorded captures, before touching the real device.
- End with the result and one lesson, such as a change to how you validate channel maps.
Follow-up
- How did you confirm the readings were correct rather than merely plausible?
- What did your code do when the instrument stopped responding mid-run?
- How did you test before the hardware was available?
What is your experience with C or C++ in the context of hardware interfacing?
Medium · Technical and Domain Proficiency
Approach
- This is an experience question, so answer it as a short story with specifics: the device, the interface (vendor C library, device file with read or ioctl, memory-mapped registers, serial or network protocol), and which parts you wrote in C versus C++.
- Show the low-level hazards you handled: fixed-width integer types, explicit byte order and bounds checks when decoding device frames instead of casting a struct over a buffer, and attention to padding and alignment.
- Show defensive I/O: every return value checked, partial reads and writes handled, timeouts, retry on interrupted calls, and a clear error path when the device does not answer.
- Describe resource discipline: RAII wrappers around file descriptors or device handles, no allocation or blocking calls in the sample-reading loop, and a ring buffer or queue between the reader and the consumer.
- Close with a bug that taught you something, such as a wrong byte order or a missing initialisation, and the test or assertion you added so it cannot return.
Follow-up
- How did you decode a binary frame safely, and why not cast the buffer to a struct?
- How did you test the interface code when the device was not on your desk?
- What happened in your code on a short read or a timeout?
Tell us about a time you had to mentor a junior engineer; what was your approach?
Medium · Behavioral and Cultural Alignment
Approach
- Pick a specific junior engineer and a specific gap, for example unsafe changes to shared code, weak debugging method or unclear commit messages. Say how you diagnosed the gap rather than assuming it.
- Describe your method: pairing on a real task, code-review comments that give the reason behind each change, a graduated task that let them own a small component, and regular short check-ins.
- Show that you let them do the work. State what you deliberately did not do for them, and what you did when they were stuck (a question, a pointer to a log or a tool, not the answer).
- Give evidence of growth: they shipped a change on their own, caught a defect in review, or began mentoring someone else. Note what you would change in your approach.
- Link it to the value of being inclusive if it fits: how you adapted to how this person learns.
Follow-up
- What did you do when your first approach did not work for them?
- How do you review a change from a junior engineer when it touches code that talks to hardware?
- How did you keep your own deliverables on track while mentoring?
How do you handle high-pressure environments where testing deadlines are critical?
Medium · Behavioral and Cultural Alignment
Approach
- Choose a real fixed date, such as a test run or release that other teams were waiting on. State the stakes in one sentence and move to your decisions.
- Show triage: you listed what had to be true for the date to hold, separated must-haves from nice-to-haves, and cut scope rather than checks.
- Explain communication: you told the people depending on you about risks early and with specifics, rather than at the deadline.
- Describe how you protected quality under pressure, such as keeping the regression run or a hardware-in-the-loop check, and what you did when something failed late.
- Finish with the outcome and a process change afterwards. Avoid a story that is only long hours; the story is your decisions.
Follow-up
- What did you choose to cut, and what did you refuse to cut?
- Did the date ever have to move, and how did you tell stakeholders?
- What did you change afterwards so the next one was calmer?
Describe a project where you had to collaborate closely with non-software engineers (e.g., mechanical or hardw
Medium · Behavioral and Cultural Alignment
Describe a project where you had to collaborate closely with non-software engineers (e.g., mechanical or hardware teams).
Approach
- Choose a project with a named non-software counterpart, for example a mechanical or hardware engineer, and say what each of you owned, such as the channel list, the interface spec or the test rig.
- Show how you built a shared vocabulary: you read their wiring diagrams or drawings, asked what a signal meant physically, and explained software limits (sample rate, latency, buffering) in terms they could use.
- Describe a disagreement, ideally over whether a fault lay in software or hardware, and how a measurement or bench test settled it rather than opinion.
- Mention the artefacts you left behind: an interface document, a channel map, a runbook, so the collaboration did not depend on memory.
- State what you learned about their constraints and how it changed your design.
Follow-up
- How did you explain a software limitation to someone who does not write code?
- Tell me about a time the other discipline was right and you were wrong.
- What written agreement did you and the hardware side keep between you?
Why do you want to work for a company that focuses on aerospace testing infrastructure?
Medium · Behavioral and Cultural Alignment
Approach
- Make it a specific answer, not a mission statement. Name what you understand about the work from what candidates report: a Linux data acquisition and control system used in ground-based jet engine testing, with software that has to interact with physical measurement hardware.
- Connect that to your own history: a project where correctness of measured data mattered, where you integrated hardware, or where reliability was a design constraint. One concrete link beats three general ones.
- Say what draws you to infrastructure and tooling for testing rather than a consumer product, for example long-lived systems, precision, and working next to hardware engineers.
- Be straight about gaps: if you have not worked in aerospace or with LabVIEW, say what you have done that is nearest and how you would close the gap.
- Address practical fit calmly, including shifts or on-site work that candidates say can apply to some roles.
Follow-up
- Which parts of your background transfer most directly to data acquisition work?
- What would you need to learn fastest in your first months?
- Are you comfortable with the on-site or shift expectations of the role?
How do you balance the need for rapid development with the requirement for high system reliability?
Medium · Behavioral and Cultural Alignment
Approach
- Do not claim you do both equally. Describe how you tier changes by risk: a logging tweak ships fast, a change to the acquisition loop or hardware interface gets more review, tests and verification.
- Name the concrete mechanisms: automated tests, a simulator or recorded data for hardware paths, code review, a staged rollout or feature flag, a rollback path, and documentation updated in the same change.
- Tell one story where you chose the slower path and what it prevented, or one where you shipped fast with known risk, how you bounded it, and how you followed up.
- Say how you measure the balance over time, for example escaped defects and rework, so the decision rests on data rather than instinct.
- Show you can still move quickly: automate the checks so reliability does not depend on manual effort.
Follow-up
- When did you ship something you knew was risky, and how did you contain it?
- How do you decide how much review a change needs?
- What did you change after a defect got through?