cswork / libraryOpen practice workspace

Interview guides · Acufore

Acufore Software Engineer Interview Guide

Acufore Software Engineer interview prep: GD&T, sheet metal, motor selection, firmware, structural integrity, the CAD tool test and a 7-day plan.

The 60-second brief

Acufore's Software Engineer role sits much closer to mechanical and hardware engineering than the title suggests. Candidates describe software that supports heavy engineering and plant design projects, with firmware integration also in scope. The requirements they report centre on CAD/CAE tools (Solidworks and Ansys by name, with Inventor also asked about), GD&T, and domain experience in structural, firmware or plant design work. In practice, the code you write here has to respect physical limits: tolerances on a drawing, the torque a motor can deliver, the load a frame can carry. Prepare to explain how your software meets those limits.

This guide is for candidates interviewing for the Software Engineer role at Acufore who have some mechanical, plant design, CAD or embedded background, or who need to build enough of it to answer domain questions credibly. It covers the five reported technical questions, the hands-on tool test candidates describe, and the HR and behavioural stage. It is not a guide to algorithm puzzles: no coding round or data-structures question has been reported for this role.

Candidates report a process that starts with an initial screen, moves to a technical deep-dive on engineering tools and fundamentals, and ends with a tool-based hands-on test. There is also an HR or behavioural conversation, where candidates say composure and body language matter. Candidates report that the whole process takes a few weeks.

Focus areas

  • GD&T (Geometric Dimensioning and Tolerancing)
  • Sheet Metal Design
  • Tool-Based Assessment (hands-on test)

Overview

The reported questions read like a mechanical design interview: which modules Solidworks, Ansys and Inventor offer, how you apply GD&T, how you approach sheet metal and choose a motor, which firmware principles you follow, and how you ensure structural integrity. None of them asks you to write code on a whiteboard. Your preparation should therefore be engineering explanations with numbers in them: a bend allowance, a reflected inertia, a position tolerance with its bonus, a factor of safety. Definitions alone will not carry these answers.

The software angle still matters. Candidates report a tip to be ready to explain how your software interacts with physical systems, and the role covers firmware and tooling around design software. For each tool, prepare one story about automating or extending it: a Solidworks or Inventor API macro, an iLogic rule, a PyAnsys or APDL script for a parametric study, or a firmware loop that drives a motor. That story turns a CAD answer into a Software Engineer answer.

The tool test is the hardest stage to fake. Candidates report that it checks practical use of the software you list on your resume, and that overstating a tool comes out there. Before the loop, trim your resume to the tools you can actually operate. Then rehearse their core workflows hands-on: a part, an assembly, a drawing with GD&T callouts, a sheet metal flat pattern, a static FEA study with a mesh check.

The HR and behavioural conversation is reported to focus on demeanour: patience, confidence, body language, and an honest account of your strengths and limits. Candidates also report that admitting you don't know a tool works better than guessing. Rehearse a calm, two-sentence way to say "I haven't used that module professionally; here is the closest thing I have done."

Where to focus your preparation

Candidates describe a screen, a technical deep-dive, a hands-on tool test and an HR or behavioural conversation. This guide treats them as one preparation block, because the number and length of the rounds have not been reported.

Preparation focus

Candidates report a process that moves from an initial screen to a technical deep-dive and ends in a tool-based hands-on test. An HR or behavioural conversation is also reported, where patience, confidence and body language are said to be watched. The technical questions candidates list are all domain questions: CAD/CAE modules in Solidworks, Ansys and Inventor; GD&T in the design process; sheet metal design and motor selection; firmware principles; and structural integrity. The hands-on test is reported to check whether you can actually use the tools on your resume. Approach the loop in that order. First make your resume honest. Then build one worked, numeric answer per reported topic. Then rehearse the core workflows of each tool you claim, hands-on rather than from memory. Finally, practise short, steady answers for the HR conversation, including how to say you don't know something.

What to demonstrate

  • Domain knowledge on the reported topics: CAD/CAE modules, GD&T, sheet metal, motor selection, firmware and structural integrity
  • Hands-on use of the CAD/CAE tools listed on your resume, as tested in the reported tool test
  • How clearly you explain engineering trade-offs and what your past projects involved
  • Composure and an honest account of your strengths and limits, as reported for the HR stage

How to prepare

  • Cut your resume's tool list to what you have used professionally, and for each tool write one project where you used it and one module you have not touched
  • Build numeric worked examples: a position tolerance with MMC bonus, a sheet metal flat pattern length, a motor sized from load torque and inertia, a factor of safety from a hand calculation
  • Rehearse core workflows hands-on in each tool you claim: part, assembly, drawing with GD&T, sheet metal flat pattern, and a static study with a mesh convergence check
  • Ask the recruiter which software the tool test uses and whether it involves modelling, drawing or simulation, then practise on that software

Where candidates lose points

Listing Solidworks, Ansys and Inventor modules you have only read about, then not being able to use them in the hands-on tool test

Claim only the modules you have actually used. For each tool, prepare one project where you used it, and say "I haven't used that module professionally" for the rest. Before the loop, rehearse the core workflows of every tool on your resume, hands-on.

Answering the GD&T question with definitions of the symbols and no worked tolerance

Walk through one real feature: the datum reference frame you chose and why, a position callout at MMC with its bonus and virtual condition computed, and a short stack-up showing it assembles.

Treating sheet metal design and motor selection as two memorised checklists with no numbers

Bring one connected example: a motor sized from load torque, reflected inertia and RMS torque over the duty cycle, mounted on a bracket whose bend allowance, flange length and stiffness you can calculate.

Giving a generic clean-code answer to the firmware question

Talk about embedded concerns. Keep ISRs short, use volatile and critical sections for shared state, avoid heap use after initialisation, use a watchdog, put actuators into a defined safe state on any fault, and keep a hardware abstraction layer so the logic can be tested on a host.

Presenting an FEA colour plot as proof of structural integrity

State the load cases, show a hand calculation that agrees within reason, describe the boundary conditions and mesh convergence study, separate singularities from real stress concentrations, and give the factor of safety against yield and buckling.

Questions & practice

Canonicalise a request body into a stable idempotency fingerprint

Medium · parsing · canonicalisation · hashing

idempotency_key.request_fingerprint is a SHA-256 over the method, path and canonicalised body, and a retry whose fingerprint differs must be rejected with 422 rather than served the stored response. Write the canonicaliser. Bodies are JSON up to 256 KB nested at most 32 levels; clients vary key order, whitespace and unicode escaping, and some send 64-bit ids as JSON numbers. Produce a deterministic byte string such that semantically identical bodies match and any semantic difference does not. State your complexity and name two normalisations you refuse to perform.

Approach

  1. Parse once into a tree, then re-serialise under fixed rules: object keys sorted, array order preserved, one escaping convention, no insignificant whitespace. Parsing is O(n) and sorting keys is O(k log k) per object, so O(n log n) overall with O(depth) stack, and the 32-level cap is enforced during parsing because hostile nesting is how a canonicaliser becomes a stack overflow.
  2. Sort keys by their UTF-8 bytes and say why the obvious implementation is wrong in some runtimes: a default string comparison that orders by UTF-16 code units places surrogate pairs, meaning code points from U+10000 up, below U+E000 to U+FFFF, which is not UTF-8 byte order, so two services written in different languages disagree on the same document.
  3. Do not re-encode numbers through a double. IEEE-754 binary64 represents integers exactly only up to 2^53, so normalising a 19-digit id through a float changes it, and 1 against 1.0 cannot be reconciled without deciding whether they are the same value. Preserve the literal token, and require ids as strings at the API boundary if you want them comparable.
  4. Reject duplicate keys rather than picking one. JSON permits them and parsers disagree, most keeping the last, so any choice you make ties the fingerprint to a parser detail that the code handling the request does not necessarily share.

Follow-up

  • A client sends the same logical request with an extra field your API ignores. Same key, different fingerprint, so you return 422. Is that the right answer?
  • Where does the fingerprint get computed relative to request decompression and the body-size limit?

Diff a projection against the primary without per-row point reads

Hard · reconciliation · range hashing · throttling

The listing projection has drifted and some rows show a stale version. The primary holds 40,000,000 resource rows across 12,000 tenants while serving 1,200 writes and 14,000 reads per second. The obvious repair, reading each resource row and comparing its version against the projection, is correct and would eventually finish. Explain precisely why it is unacceptable here, then give a diff that finds the differing rows, state its complexity, and make it safe to run against a live primary. Replication lag is usually under 100 ms and is not bounded.

Approach

  1. Quantify the naive cost rather than calling it slow: 40,000,000 point reads at even 0.5 ms each is over five hours serialised, and the only lever is concurrency, which is exactly what you cannot spend. The primary's pool is sized for the write path, and 40,000,000 random reads evict the buffer cache that sustains the 85 percent cache hit rate, so the audit degrades the system it is auditing.
  2. Replace random access with one ordered pass per side. Both sides can be read in (tenant_id, resource_id) order, which is a sequential scan on each and a merge join in O(n) time and O(1) memory. For a dense diff that is the whole answer, and it reads the primary once instead of 40,000,000 times.
  3. For the expected sparse case, compare range hashes instead of rows: partition the key space, compute per range an order-independent aggregate over hash(resource_id, version), compare aggregates, and descend only into ranges that differ. With d differing rows and branching factor B, at most d ranges mismatch per level, so the drill-down examines O(d log_B(n/d)) ranges and reads full rows only in mismatching leaves.
  4. Aggregate with a sum modulo 2^64 or a multiset hash, never XOR. XOR is order-independent but self-cancelling, so two rows wrong in the same way, or a row duplicated on one side, leave the range aggregate matching and the range is declared clean.

Follow-up

  • The diff reports 900 stale rows. How do you decide between patching those rows and rebuilding the projection from resource_revision?
  • Same job, but the projection lives in a search index that cannot be scanned in key order. What changes?

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

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

Explain why the owner filter ignores the listing index

Medium · composite index · query plans · sort elimination

The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.

Approach

  1. Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
  2. For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
  3. Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
  4. Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.

Follow-up

  • 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
  • A dashboard runs this for 40 owners in one page load. What changes about the design?

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

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

Explain the different modules in Solidworks, Ansys, and Inventor.

Medium · Technical & Domain Expertise

Approach

  1. Group the modules by workflow stage instead of reciting menus: geometry creation, analysis, documentation and data management. For each tool, name the modules you have used and say what you produced with each.
  2. Solidworks: Part, Assembly and Drawing environments; Sheet Metal and Weldments features; Toolbox for standard hardware; Simulation for static, frequency, buckling, thermal and fatigue studies; Flow Simulation for CFD; Motion for kinematics; Routing for piping and electrical; PDM for vault and revision control.
  3. Ansys: Workbench ties the analysis systems together. Mechanical covers static structural, modal, harmonic, transient and buckling analysis; Fluent and CFX cover CFD; SpaceClaim or Discovery handle geometry cleanup; Maxwell covers electromagnetics (relevant to motors); LS-DYNA covers explicit dynamics; Icepak covers electronics cooling.
  4. Inventor: Part (.ipt), Assembly (.iam), Drawing (.idw/.dwg) and Presentation (.ipn); Frame Generator, Sheet Metal, Design Accelerator (shafts, gears, bolted joints, bearings), Stress Analysis, Dynamic Simulation, Tube & Pipe, Cable & Harness, iLogic for rule-based automation, and Vault for data management.
  5. Close with the software engineer's angle: automation through the Solidworks API (COM, from VBA or C#), the Inventor .NET API or iLogic, and PyAnsys or APDL for scripted parametric studies. Say plainly which modules you know only by name, because the tool test will check the rest.

Follow-up

  • When would you run an analysis in Solidworks Simulation instead of Ansys Mechanical, and when is that not enough?
  • How would you automate generating drawings for 200 configurations of one part?
  • How do you check that a mesh is fine enough before trusting a stress result?

How do you apply GD&T (Geometric Dimensioning and Tolerancing) in your design process?

Medium · Technical & Domain Expertise

Approach

  1. Start from function: choose datums from the features that locate the part in its assembly. The primary datum contacts at a minimum of three points and removes three degrees of freedom, the secondary two and the tertiary one, so the datum reference frame removes all six.
  2. Name the five control groups and pick the right one for each feature. Form: flatness, straightness, circularity, cylindricity. Orientation: perpendicularity, parallelism, angularity. Location: position. Profile: of a line, of a surface. Runout: circular, total. Note that ASME Y14.5-2018 removed concentricity and symmetry, while ISO GPS keeps them.
  3. Work one number. Take a hole of Ø10.0 ±0.1 with position Ø0.2 at MMC. MMC is 9.9, so at 10.1 the bonus is 0.2 and the allowed position zone grows to Ø0.4. The virtual condition is 9.9 − 0.2 = 9.7, which is the size of the fixed gauge pin.
  4. Size tolerances from the mating part. For a floating fastener, T = H − F at each part (hole MMC minus fastener MMC). For a fixed fastener, the two parts share H − F. Then run a stack-up: worst case when every part must fit, RSS when volumes are high and processes are centred.
  5. Tie it to software: say how you put GD&T into the model as PMI or MBD (DimXpert in Solidworks, Tolerance Analysis in Inventor). If you have done it, mention a script that runs stack-ups automatically.

Follow-up

  • Calculate the position tolerance for a two-plate bolted joint with M8 bolts in Ø9.0 holes.
  • Why use profile of a surface instead of plus-and-minus dimensions on a contoured part?
  • When is an RSS stack-up defensible, and when would you insist on worst case?

Can you explain your approach to sheet metal design and motor selection?

Medium · Technical & Domain Expertise

Approach

  1. Sheet metal: pick the material and gauge from load and environment, then design to the press brake. Keep the inside bend radius at least equal to material thickness for mild steel (larger for harder alloys and aluminium tempers), keep bend radii uniform to limit tool changes, add bend reliefs, and keep holes and cut-outs a few thicknesses away from bends.
  2. Show the flat pattern maths. Bend allowance is BA = (π/180)·θ·(R + K·T), with K usually between 0.3 and 0.5. Bend deduction is BD = 2·tan(θ/2)·(R + T) − BA. Say that you calibrate the K-factor against a test bend from the actual shop, not a default table.
  3. Motor selection: start from the motion profile. Peak torque is J_total·α plus friction plus load torque. Reflect the load through the transmission: J_load/N² for a gearbox of ratio N and T_load/(N·η) for torque. For a lead screw, T = F·L/(2π·η). Check that RMS torque over the duty cycle is below continuous rating and that peak torque is below peak rating, with margin.
  4. Choose the motor type on purpose. A stepper is simple and open loop, but its torque falls with speed and it can lose steps. A servo or BLDC with an encoder suits dynamic axes. An AC induction motor suits constant-speed drives. Keep the load-to-motor inertia ratio inside the vendor's recommended range and check the torque-speed curve at the operating point.
  5. Connect the two halves: the sheet metal bracket that carries the motor must take the reaction torque and vibration without flexing. Mention stiffening flanges or gussets, and a modal check so the bracket's natural frequency stays clear of the motor's excitation frequency.

Follow-up

  • Size a motor for a horizontal conveyor carrying a given load: what inputs do you need first?
  • Stepper or servo for a pick-and-place axis, and why?
  • Your flat pattern comes out of the brake 0.5 mm long on every part. What do you change?

What are the core principles you follow when working on firmware development?

Medium · Technical & Domain Expertise

Approach

  1. Determinism first. Keep interrupt service routines short, set a flag or push into a ring buffer, and do the work in the main loop or an RTOS task. Run control loops such as PID at a fixed rate from a timer, not from whenever the main loop gets round to them.
  2. Shared state between interrupts and the main code: mark it volatile. But volatile does not make access atomic, so protect multi-byte or read-modify-write accesses with a critical section or atomic instructions, and avoid calling non-reentrant functions from an ISR.
  3. Memory and robustness: no dynamic allocation after initialisation, a measured stack size, bounded loops, input validation on every sensor reading, and a coding standard such as MISRA C/C++ checked by static analysis.
  4. Fail safe around actuators. Use a watchdog that is fed only when the main loop is healthy, brown-out detection, and a defined safe state such as motor off or brake engaged on any fault, at reset and after a lost communication link. For field updates, use a bootloader that keeps a fallback image.
  5. Testability: put a hardware abstraction layer between drivers and logic so state machines and control code can be unit tested on a host. Then confirm on hardware with a debugger over JTAG/SWD, a logic analyser and an oscilloscope.

Follow-up

  • How do you share a 32-bit encoder count between an ISR and the main loop on an 8-bit microcontroller?
  • A motor controller resets intermittently only under load. How do you debug it?
  • How do you test firmware logic before the board exists?

How do you ensure structural integrity in your designs?

Medium · Technical & Domain Expertise

Approach

  1. Define the load cases before modelling anything: static working load, dynamic and impact loads, fatigue from repeated cycles, thermal loads, and lifting, transport and installation cases, each with its source.
  2. Do hand calculations first so you can sanity-check the FEA: bending stress σ = M·c/I, beam deflection, Euler buckling P_cr = π²EI/(KL)² for slender members, and bolt and weld checks. Factor of safety is the allowable (usually yield for ductile steel) divided by the peak working stress. For steel structures, also say which design code governs.
  3. In FEA (Ansys Mechanical or Solidworks Simulation), clean up the geometry, apply realistic boundary conditions (over-constrained fixtures inflate stiffness) and run a mesh convergence study. Read von Mises stress for ductile materials. A stress that keeps rising at a sharp re-entrant corner as the mesh is refined is a singularity, not a real result: fillet the corner or evaluate stress away from it.
  4. Check stiffness and dynamics as well as strength: deflection limits, a modal analysis to keep natural frequencies away from motor or pump excitation, and fatigue at welds, holes and other stress concentrations using an S-N curve.
  5. Close the loop with validation: compare against the hand calculation, and against strain gauges or a load test where the risk justifies it. As a software engineer, mention scripting parametric sweeps so that every design change reruns the checks.

Follow-up

  • Your FEA peak stress is three times your hand calculation. What do you check first?
  • How do you choose the factor of safety for a lifting frame compared with a machine guard?
  • How would you detect and handle a resonance problem in a motor-mounted frame?

p99 jumped on one listing filter while p50 stayed flat

Medium · query planning · composite index · percentiles

After a release that added an owner_user_id filter to the resource listing, p99 rose from 90 ms to 1.9 s while p50 stayed at 40 ms. Traffic and row counts are unchanged. resource carries the index (tenant_id, status, updated_at DESC, resource_id DESC). The new query filters tenant_id and owner_user_id, orders by updated_at DESC, resource_id DESC, and takes 20 rows. On PostgreSQL, explain the shape of the regression, prove it from a query plan, and give the index you would add.

Approach

  1. Start from the shape. A flat p50 with a moved p99 means a subset of requests changed cost, not all of them, so the first job is naming the subset. Bucket the endpoint's latency by the tenant's row count; the natural hypothesis is that large tenants are a small share of requests and all of the tail.
  2. Get the plan for the new query on a large tenant with EXPLAIN (ANALYZE, BUFFERS). Expect an index scan over the tenant's range, a filter discarding most of it, then a Sort feeding the Limit, possibly reporting Sort Method: external merge Disk. Read actual rows on the scan node, not estimated.
  3. Explain why the existing index cannot serve it. A composite B-tree is seekable only as a left prefix, and with no equality predicate on status the scan cannot treat updated_at as an ordering, because rows in the tenant's range are ordered by status first. Everything matching must be read and sorted before LIMIT 20 can apply, so a tenant with 400,000 rows pays 400,000 rows to return 20.
  4. Add (tenant_id, owner_user_id, updated_at DESC, resource_id DESC). Equality on the first two columns leaves the index ordered by updated_at within that pair, so the plan becomes an index scan that stops after 20 rows with no Sort node. PostgreSQL can scan a B-tree backwards, so the DESC markers matter only if the two sort columns ever disagree in direction; keeping them explicit documents the order the keyset cursor depends on.

Follow-up

  • The endpoint paginates with OFFSET. What does page 500 cost with your index, and what does the keyset version cost?
  • How would you have caught this before release, given that a 10,000-row seed database produces the same plan shape at an unnoticeable cost?

Suggested practice checklist

Each day covers one reported question or the reported tool test, and produces a written or hands-on artefact you can reuse in the loop. The last day covers the HR conversation and a full mock.

Day 1 — Audit your tools and confirm the tool test

  • List every CAD/CAE tool and module on your resume, and mark each one as used professionally, used once, or known only by name
  • Remove or qualify anything in the last two groups, then ask the recruiter which software the tool test uses and what kind of task it involves
  • Write a one-line summary of each module you have used in Solidworks, Ansys and Inventor, with the project it was used on

Deliverable: A cleaned tool list, the recruiter's reply on the tool test, and a module-by-project table for the three tools.

Day 2 — GD&T with numbers

  • Pick a real part you designed and mark the datums you would choose, with the functional reason for each
  • Write a position callout at MMC on one hole pattern, then compute the bonus tolerance and virtual condition
  • Run a worst-case and an RSS stack-up for one assembly gap, and answer the GD&T question out loud

Deliverable: A marked-up part sketch, a written bonus and virtual-condition calculation, and a two-method stack-up.

Day 3 — Sheet metal and motor selection

  • Model a sheet metal motor bracket in your strongest CAD tool, then check its flat pattern against a hand bend-allowance calculation
  • Size a motor for a lead-screw or conveyor axis: reflected inertia, peak torque, RMS torque and the choice between stepper and servo
  • Answer the sheet metal and motor selection question out loud, linking the bracket to the motor's reaction torque

Deliverable: A bracket model with a verified flat pattern, a one-page motor sizing sheet, and a recorded spoken answer.

Day 4 — Firmware principles

  • Write a short C or C++ example of an encoder ISR that shares a count with the main loop safely
  • Outline the fault handling for a motor controller: watchdog, brown-out, safe state and fallback after a failed update
  • Answer the firmware question out loud, using one past embedded project as the example

Deliverable: A compiled ISR example, a fault-handling outline, and a recorded spoken answer.

Day 5 — Structural integrity and FEA

  • Hand-calculate bending stress, deflection and buckling load for a simple frame member
  • Run the same member as a static study in Ansys or Solidworks Simulation with a mesh convergence check, and compare the result
  • Add a modal study and note how far the first natural frequency sits from a motor's running speed

Deliverable: A hand calculation, an FEA result with its convergence table, and a written comparison including the factor of safety.

Day 6 — Tool test rehearsal and the software angle

  • Hands-on: make a part, an assembly and a fully dimensioned drawing with GD&T callouts, as quickly as you can, in the tool the recruiter named
  • Write or revisit one automation for a tool you claim: a Solidworks or Inventor API macro, an iLogic rule or a PyAnsys script
  • Answer the CAD/CAE modules question out loud again, this time ending with the automation story

Deliverable: A completed part, assembly and drawing set, a working automation script, and a final spoken answer on modules.

Day 7 — HR conversation and full mock

  • Write STAR stories on strengths and limits, explaining a technical constraint to a non-specialist, and handling two project streams
  • Practise a calm answer to a question on a tool you do not know
  • Run a full mock covering all five technical questions with a friend, then review your pace and posture on video

Deliverable: Three written STAR stories, a rehearsed "I don't know that tool" answer, and notes from a recorded mock.

Behavioural preparation

Candidates report that the HR and behavioural stage looks at patience, confidence and body language, and at whether you describe your strengths and limits honestly. The role is also reported to involve explaining technical constraints to non-technical stakeholders and managing several project streams. Use STAR answers with a measurable result, and keep your delivery steady.

  1. What are your strengths and limitations as an engineer? Give one concrete example of each.
  2. Tell me about a time you explained a technical constraint, such as a tolerance, a load limit or a timing budget, to someone without that background, and what they decided as a result.
  3. Walk me through one project on your resume: what you owned, the hardest engineering problem, and the measurable result.
  4. Describe a time you were asked about a tool or method you did not know. What did you say, and what did you do next?
  5. Tell me about a period when you ran two project streams with competing deadlines. How did you decide what slipped?

Reverse your own decision and price the reversal

Medium · reversibility · measurement · migrations

Describe a technical decision you made and later reversed. Pick one that cost something: a service you split and merged back, a cache you added and removed, an index you created that pushed the planner onto a worse plan, a projection you rebuilt from scratch. State what you believed when you decided, the measurement that changed your mind, how long the wrong version ran in production, and what the reversal cost in migrations, dual writes, and a deprecation window for callers you did not own.

Approach

  1. State the original rationale without irony, in the version you would still defend given what was known then. If it is not defensible, the story is about carelessness rather than judgement, and a different example serves you better.
  2. Give the measurement that moved with a before and after: the p99 that did not improve, the cache hit rate that sat at 40%, the plan that flipped to a sequential scan once the table passed a size you can name.
  3. Cost the reversal in steps, not adjectives: expand-and-contract deploys, the dual-write window, the callers who had to be notified, the rows already written in the wrong shape that had to be backfilled or abandoned.
  4. Distinguish reversal from rewrite by naming what you kept. Most good reversals preserve the schema or the interface and undo one decision inside it, which is also why they were affordable.

Follow-up

  • What in that decision was irreversible, and did you know it was irreversible when you made it?
  • How did you tell the people who had already built on top of the original decision?

Argue against a design, lose, and commit anyway

Medium · disagreement · service boundaries · decision records

Describe a design you argued against and lost. State the failure you predicted as a named mechanism, not a feeling about complexity: two services that would need one transaction, a projection with no rebuild path, a write path with no idempotency key. Say what evidence you brought, what the decision maker weighed instead, and what you did after the decision was made: what you instrumented, what you wrote down, and whether the prediction came true. Five minutes.

Approach

  1. State the prediction in falsifiable form up front: the mechanism, the condition that triggers it, and the observable outcome. A prediction that cannot be checked also cannot be credited to you later.
  2. Show the evidence you had at the time and label each piece honestly as measured, analogous, or intuition. Keeping the intuition is fine; disguising it as data is the thing that erodes your standing in the next argument.
  3. Represent the opposing case at full strength, including the constraint you did not control: a fixed date, a team boundary, or the fact that the decision was cheap to reverse and yours was not.
  4. Make disagree-and-commit concrete. Name the artefact you left behind so the prediction could be settled without you: the alert and its threshold, the counter on the dashboard, the decision note that recorded the trade-off and the condition that would revisit it.

Follow-up

  • What threshold on that alert would have proved you right, and did anyone ever look at it?
  • If the same proposal arrived tomorrow with the same deadline, would you argue it the same way?

Ship under a deadline and bound the debt you chose

Medium · pagination · technical debt · tradeoffs

You have four days to ship a tenant-facing listing endpoint. The version you would defend uses keyset pagination over (tenant_id, status, updated_at DESC, resource_id DESC); the version you can finish uses LIMIT/OFFSET with no matching index. Describe a deadline call you actually made of this shape: what you shipped, what you knowingly deferred, how you bounded the damage with a mechanism rather than an intention, and the specific numeric condition that would force the follow-up. Name who you told and where you wrote it down.

Approach

  1. Name the deferred failure precisely instead of calling it slow. OFFSET n makes the database produce and discard n rows, so cost grows with page depth; without an index matching the sort, every matching row is read and sorted before the limit applies; and rows inserted between two page fetches shift across the boundary so items are skipped or repeated with nothing in the response to signal it.
  2. Bound the blast radius with something mechanical rather than a promise: cap maximum page depth, cap page size, restrict the endpoint to one internal caller, or keep it behind a flag. State which failure each cap removes and which it leaves standing.
  3. Attach a number to the trigger and wire it to an alarm: the first tenant crossing N resources, or the endpoint's p99 crossing its share of the 400 ms budget, so the debt announces itself instead of waiting to be remembered.
  4. Write it where the next engineer looks, which is the code and the ticket, not a chat message: what was deferred, why, the cap, and the trigger.

Follow-up

  • At what page depth does the offset version breach your latency budget, given your page size and row counts?
  • What breaks first when you switch to keyset pagination later, and what does a client holding an old page token see?