As a Software Engineer at Terex Corporation, you are not just writing code; you are building the digital intelligence that powers world-class lifting and material processing machinery. Terex Corporation operates at the intersection of heavy industrial engineering and modern technology, requiring software solutions that are as robust and reliable as the physical equipment itself. Your work directly influences the efficiency, safety, and operational capability of Terex Corporation's global product lines.
You will contribute to a complex ecosystem where software interacts with mechanical, hydraulic, and electrical systems. Whether you are optimizing control logic, developing diagnostic interfaces, or integrating cloud-based data solutions, your contributions enable Terex Corporation's customers to tackle the most demanding infrastructure and construction challenges. This role is ideal for engineers who thrive on seeing their code manifest in high-stakes physical environments where precision and performance are non-negotiable.
Initial Screening
reportedThe title covers product work, platform work, infrastructure, mobile and frontend, and those are different jobs with different loops behind them. A screening call is the cheapest place to find out which one the seat is, and asking reads as experienced rather than fussy. The questions that separate them: what the team is on call for, what the last three projects were, and whether any round happens inside an existing repository instead of a blank file. Then say which of that you have done and which you have not. Claiming the whole posting is the fastest way to be found out one round later.
What to demonstrate
- Whether you can locate your experience inside one flavour of the role honestly instead of claiming the entire requirements list
- Whether you name what you have not done, which an experienced screener reads as a level signal and can plan the loop around
- Whether what you want next matches what the seat is: someone who wants greenfield work landing on a team that mostly operates an existing system is a hire that leaves within the year
How to prepare
- Mark every line of the posting as done, adjacent or new, and write one sentence for each adjacent line naming the closest thing you actually built
- Split your last two years into rough percentages across feature work, operating and debugging live systems, and design or review, so a question about scope gets numbers rather than adjectives
- Bring three questions that discriminate between seats: what the team is paged for, how much of the work is changing existing code versus standing up something new, and what shipped in the last quarter
Formal Interview Stage
reportedYou cannot drill a format you do not know, so put the preparation into material that travels. Three pieces of your own work, each rehearsed until you can take a follow-up you did not anticipate, will carry a conversation or a code walkthrough equally well. Specificity is what separates that from filler. A number needs its definition before it means anything: a p99 is over some window and measured at some hop, and a server-side figure excludes the queueing and network time a client would see. The number you cannot qualify is the one to leave out.
What to demonstrate
- Whether your examples carry detail only someone who did the work would hold, such as what the binding constraint actually was, which alternative you rejected and why it was worse, and what you measured on each side of the change
- Whether a number survives one follow-up, meaning you can say what it was measured over and whether it moved because of your change or merely alongside it
- Whether a failure is described with the specific change that followed it, rather than a lesson stated in general terms
- Whether your part in a team effort is stated accurately, including what other people did
How to prepare
- Write a page on each of three projects covering the constraint, the option you rejected, the measurement before and after, and what went wrong. Cut any line you cannot take a follow-up on, since you are writing the parts you will be pressed on rather than a summary.
- Recover the real figures while you still have access: request volume, data size, latency with its percentile and window, team size, timeline. Note where each came from, whether a dashboard, a design document or memory, and mark the estimates so you can say which they are out loud.
- Take your weakest project story to someone who works in a different area and have them ask why four times in succession. The point where you run out of answer is the part to go and re-read before the round.
Resume Walkthrough
reportedHalf of this call is the part candidates treat as small talk: start date, notice period, work authorisation and its timing, location and time zone, on-call, and the number. Those are what kill offers late, after several engineers have each spent a day. Surfacing a hard constraint now costs you nothing and occasionally buys you something, since a loop compressed to fit a competing deadline can usually only be arranged if it is asked for early. The common failure is deflecting the compensation question twice, then discovering at offer stage that the band never reached your number.
What to demonstrate
- Whether your hard constraints are compatible with the role before a loop gets booked: earliest start, notice period, what authorisation you hold and when it needs action, days on site, willingness to carry a pager
- Whether you give a compensation range with something behind it, such as current total compensation or a competing timeline, rather than leaving the band untested
- Whether your stated timeline is real, since a competing deadline raised now is something scheduling can sometimes work around and the same deadline raised at offer stage usually is not
How to prepare
- Write each constraint down in one line before the call and state them as facts rather than negotiating them live under a question you were not expecting
- Set your range from two or three current data points for that level and location, and name the structure you are quoting in, so the number is comparable to the one they are holding
- If another process is running, say where it stands and by when, and ask directly whether this loop can be scheduled inside that window
Situational Problem Solving
reportedWhen a round has no standard shape, it is often there because something is still open: an area no earlier conversation reached, a round where the signal came out mixed, or a decision someone is not ready to make alone. Work out which by going back over what each earlier round actually covered rather than how it felt, and arrive able to give evidence on that point without being asked twice. Weak answers replay the loop's earlier material at the same depth. Strong ones go a level deeper and stay consistent with what you already said.
What to demonstrate
- Whether your account of a project matches the one you gave earlier in the loop, since what you said before may be available to whoever runs this round
- Whether you can go a level deeper on something already covered, reaching the decision and its alternatives rather than repeating the summary
- Whether you state your own uncertainty accurately, including parts of a system you did not build and decisions you inherited, instead of claiming even ownership across all of it
- Whether you can answer a question you handled poorly earlier by naming what you missed, rather than delivering a polished second version as if the first had not happened
How to prepare
- Reconstruct the loop on one page: for each round, the questions you were asked and the answer you actually gave, not the better one you thought of afterwards. The gaps on that page are your best available guess at why this round exists.
- Take the two claims you made earlier that carry the most weight and assemble the backing for each: the measurement, the date, what broke, the decision you would make differently now.
- Write down the three facts about your work that must not drift between tellings, such as team size, timeline and your own role, and check your stories against that list rather than trusting recall under pressure
PracHub editorial advice for the preparation topics above.
Judging delivery windows and cut-offs in UTC
A delivery appointment, a receiving cut-off and a same-day promise are all statements about local wall-clock time at a specific stop, so evaluating them in UTC misclassifies on-time performance for any leg that crosses a zone, and misses cut-offs by an hour on the two days a year a region changes offset. The subtlety that catches experienced engineers is that converting a future local time to a UTC instant at write time bakes in the offset rules as they were known then: when a jurisdiction changes its rules, an appointment stored that way silently moves, which is why a future window is better stored as local wall time plus an IANA zone identifier and resolved at read time, while a past event is correctly stored as an instant. Duration arithmetic needs the same care, because a transit that spans a DST boundary is genuinely 23 or 25 hours long in local terms even though the elapsed instant count is unchanged. Storing only a date with no zone - common on partner feeds - is the version of this that cannot be fixed downstream, so the zone has to be captured at ingestion.
Ordering events by arrival rather than by event time
Offline handhelds, batch partner feeds and store-and-forward gateways deliver observations out of order as a matter of course, so a pipeline that folds whatever arrived last will flap a delivered shipment back to in transit and recompute on-time performance from the wrong facts. Message-broker ordering guarantees do not rescue this: per-partition ordering only holds within a partition, so unless the producer keys by the entity being tracked, two events for one leg can land on different partitions and be processed concurrently. The defence has two halves that are often confused - deduplicate on a stable key, then fold with a monotonic status lattice ordered by occurred_at - and both are needed, because deduplication alone still lets a stale event win. Note also that occurred_at is device-reported and therefore sometimes wrong, which is why storing received_at and a measured clock offset beside it is what makes event-time logic auditable instead of merely plausible.
Not asking what the system looks like if it dies halfway through
For any multi-step write, say what state remains if the process stops between step two and step three, and what brings it back: a single transaction, a saga with compensating actions, an outbox, or a reconciliation job. Partial failure is routine at any real call volume, so 'that shouldn't happen' is an answer with nothing behind it.
Check-then-act on shared state
Read, decide, write is not safe under concurrency unless the decision and the write are one atomic step: a unique constraint with conflict handling, a compare-and-set, or a row lock held for the whole transaction. Two requests can both pass the existence check before either inserts, which shows up as duplicate rows under load and never in a single-threaded test.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Re-sum a movement ledger and report positions that disagree
inventory_movement holds 3 billion immutable rows: item_id, node_id, lot_id (NULL when the item is lot-untracked), state, delta_qty (signed int64 in the item's smallest transacting unit), uom_code, and reversed_by. inventory_position holds one row per (item_id, node_id, lot_id, state) with qty, version and last_movement_id, using lot_id = 0 as the sentinel for untracked. Up to 80 million distinct keys. Report every key whose summed movements disagree with the stored qty, while writes continue. State your time and space bounds and how you bound the comparison.
Approach
- Fix the key first.
inventory_movement.lot_idis NULL for untracked items andinventory_position.lot_idis 0, so the group key is(item_id, node_id, COALESCE(lot_id, 0), state). Getting this wrong does not error — it silently produces two groups that each look like a variance, and the report becomes noise nobody reads. - Cut the ledger at a watermark, but do not take
W = max(movement_id)at the start of the scan. A sequence hands out an id before the inserting transaction commits, so at the instant you read that maximum there are ids below it still in flight and invisible to your snapshot. Summingmovement_id <= Wmisses them on this run, and advancingreconciled_through_movement_idtoWmakes the miss permanent: every later incremental run starts above those ids and they are never summed again. That is a hole in the ledger's own re-derivation, not a transient skew. - Take a watermark that is provably settled instead. Bound write transactions with a statement or transaction timeout so 'the longest write' is a number T, record
(observed_at, max_movement_id)samples periodically, and use asW_safethe largest sampled id whoseobserved_atis older than T — every id at or below it has committed or rolled back. Sum rows withmovement_id <= W_safe, compare only against position rows withlast_movement_id <= W_safe, treat anything newer as a write that raced you rather than a variance, and advancereconciled_through_movement_idonly toW_safeso the next run starts there instead of re-reading 3 billion rows. If the ledger carries a commit timestamp, cutting on that is the same guarantee without the sampling table. - Sum
delta_qtyas int64, and include reversal rows.reversed_byis a back-pointer for audit, not an exclusion filter: an original of +10 and its reversal of -10 must both be summed to reach 0. Excluding the original while keeping the reversal produces -10 and a false variance on every corrected key. - Guard the denomination rather than trusting it.
uom_codeis stored per row because pack factors change over time, so reject — do not sum — any row whoseuom_codeis not the item's smallest transacting unit, and report those keys separately. A mixed-denomination sum is arithmetically meaningless and looks exactly like a real variance. - Hash aggregation is O(n) time and O(distinct keys) space: 80 million entries at roughly 40-56 bytes each in a typical runtime is 3-5 GB, so quote the number. The bounded-memory alternative is an external sort-merge on the group key — O(n log n) comparisons, resident memory bounded by the merge fan-in rather than by key count, and it streams — or hash-partition by
hash(item_id) % Pand run P independent passes for 1/P of the peak.
Worked solution 25 min
- Write the group key expression down explicitly, including the NULL-to-0 mapping, before any aggregation code.
- Derive
W_safefrom a sample older than the transaction-duration bound T, and state in one sentence which rows on each side are in scope — this is the part that makes the report trustworthy under live writes, and the part that decides whether an in-flight row is re-read next run or lost forever. - Implement the hash aggregation with an int64 accumulator and a
uom_codeassertion per row, emitting rejected rows to a second output rather than into the sum. - Build a fixture with four keys: one clean, one with a movement missing from the position, one with an original plus its reversal, one with a row in cases where the item transacts in eaches.
- Run it, then re-run with the fixture rows shuffled, with a concurrent writer appending past the watermark, and with a writer that reserved an id below
max(movement_id)and commits only after the scan finishes — then run the incremental pass and confirm that row is summed there.
Follow-up
- A key shows a variance of exactly one pick, repeatedly, at one node. What do you look at first, and what would distinguish a duplicate movement from a missed one?
- The job takes six hours and the variance report is stale by the time anyone reads it. How would you make it incremental without losing the guarantee that it re-derives from the ledger?
- Who writes the correcting movement, and what reason code does it carry?
Split an order across the fewest nodes that can fill it
A fulfilment order has L lines, L up to 25. After filtering by capability, service time and stock, N candidate nodes remain; N is usually under 14 but can reach 200. Each node covers a known subset of the lines in full. Return a minimum-size set of nodes covering every line, tie-broken by total distance. Give an exact algorithm for the small case with its exact cost in operations and bytes, say precisely why enumerating node subsets stops working, and give what you ship when N is 200.
Approach
- Name it: this is minimum-cardinality set cover, which is NP-hard, so the useful move is choosing which parameter you are exponential in rather than hunting for a polynomial exact algorithm. Enumerating subsets of nodes is 2^N and correct — at N = 14 that is 16,384 subsets and finishes instantly, which is exactly why it survives review and then fails in production at N = 200, where 2^200 is about 1.6e60.
- Be exponential in L instead, because L is the parameter you bound. Index the DP by the set of lines still uncovered:
dp[rem]is the cheapest way to cover the lines inrem, withdp[0] = (0, 0)and the value a(node_count, total_distance)pair compared lexicographically. Letbbe the lowest set bit ofrem; any cover must contain some node that stocks lineb, so the transition ranges only over those nodes:dp[rem] = min over v with b in cover(v) of dp[rem & ~cover(v)] + (1, dist(v)). Worst case O(2^L * N) — at L = 25 and N = 14 that is 33,554,432 states times 14, about 4.7e8 transitions — and the lowest-bit restriction cuts the real branching factor to the nodes stocking one specific line. - Quote the memory for what you actually store, not for a count array alone. Over 2^25 masks you need three dense arrays:
uint8node count (33.5 MB),uint32total distance (134.2 MB, integer metres so the tie-break compares exactly and the array stays fixed-width), anduint8chosen node (33.5 MB, since N <= 200 fits a byte) — about 201 MB, roughly six times the 33.5 MB that a bare count array would suggest. The same layout at L = 20 is 6.3 MB, which is why this is comfortable up to about 20 lines and needs a deliberate decision at 25. - Reconstruction is free in this formulation and needs no parent-mask array: because every transition eliminates the lowest uncovered line, the predecessor of
remunder the stored choicevis exactlyrem & ~cover(v), so walkremfrom the full mask down to 0 emittingchoice[rem]. If the reachable state count is far below 2^L — coverage sets are usually highly correlated — a top-down memoized recursion over a hash map trades the 201 MB for roughly 40-60 bytes per visited state; measure the visited count first, because a hash map that ends up touching most masks is strictly worse than the dense arrays. Add a branch-and-bound cut ofceil(popcount(rem) / max_v popcount(cover(v) & rem)), which prunes long before the theoretical bound bites. - When exact is out of reach, ship greedy with a stated guarantee: repeatedly take the node covering the most currently-uncovered lines, using bitset popcounts, O(N * ceil(L/64)) word operations per pick and at most min(N, L) picks. Greedy is within H(L) <= ln L + 1 of optimal (Chvatal), and no polynomial algorithm achieves (1 - o(1)) ln L unless P = NP (Dinur and Steurer, 2014) — so effort belongs in the pre-filter and the tie-break, not in a cleverer heuristic. At L = 25 the bound is H(25), about 3.82x worst case, while the realistic gap on correlated coverage sets is zero or one node.
- Close on the objective, because fewest nodes is not cheapest. Two shipments from distant nodes routinely cost more than three from near ones, and a split also costs a second box, a second carrier pickup and a worse customer experience. If cost is the real objective it is weighted set cover — greedy by cost divided by newly-covered lines, same logarithmic bound — and if a node can cover a line only partially, the line mask is no longer sufficient state, since you must track remaining quantity per line; that is the point at which you stop hand-rolling and either restrict splits or hand an MILP to a solver with a time budget.
Follow-up
- The pre-filter is what keeps N small. What is in it, and what happens to your exact path the day someone loosens it?
- One node can cover a line only partially. Show where the bitmask formulation breaks and what state replaces it.
- You have 40 milliseconds inside a checkout call. Which of these runs there, and what runs asynchronously afterwards?
Find the hottest write keys under a fixed memory budget
One day of writes to inventory_movement is 200 million rows; each carries (item_id, node_id). Distinct pairs reach 60 million. Return the 200 pairs with the most writes so they can be moved behind a single writer before the next peak. First give the exact answer assuming you may hold 60 million counters, then give an answer under a 200 MB budget, and state the error guarantee that second answer carries. Both must be one pass over the day's rows unless you argue for a second.
Approach
- Exact version: one hash pass to build
(item_id, node_id) -> int64, then a single scan of the map maintaining a min-heap of size K = 200, pushing and popping when the incoming count exceeds the heap root. O(n + d log K) with n = 2e8 and d = 6e7, versus O(d log d) if you sort all 60 million entries — a factor of roughly log d / log K, about 3.4x, for no benefit. The heap must be a min-heap: the root is the weakest survivor, so eviction is O(log K). - Cost the map honestly. 60 million entries at a 16-byte key, an int64 count and per-entry overhead is 2-3 GB in most runtimes, which is the whole reason for the second version rather than a theoretical aside.
- Bounded version: Misra-Gries with m counters. Keep at most m keys with counts; on a key already present increment it; on a new key when fewer than m are held, insert at 1; otherwise decrement every held counter and drop those reaching zero. With m = 1,000,000 at roughly 40 bytes per counter, that is about 40 MB, comfortably inside 200 MB alongside the heap.
- State the guarantee as a number, not as 'approximate'. Misra-Gries returns an estimate satisfying f - n/(m+1) <= f_hat <= f, so with n = 2e8 and m = 1e6 every count is an undercount by at most 200. If the 200th hottest pair has hundreds of thousands of writes, a 200-count error cannot reorder the top of the list — and if the counts near rank 200 are within 200 of each other, the ranking there was never meaningful for the decision being made. The sketch also merges: run one per shard, combine, prune back to m, and the bound holds with n the combined length.
- If exactness is genuinely required, argue for two passes rather than more memory: the Misra-Gries pass yields a candidate superset of size m, and a second pass counts only those candidates exactly in O(m) memory. That is the standard way to get an exact top-K under a memory bound, and the cost is one extra read of the day's rows.
Follow-up
- The decision downstream is which keys get a single writer. Does a rank error at position 190 change that decision, and what does the answer tell you about how much accuracy to buy?
- Write volume on one key is bursty — a promotion concentrates it into twenty minutes. Does a daily top-K find it, and what window would?
- How do you keep the sketch across a worker restart without replaying the day?
Stop two allocators promising the same unit of stock
inventory_position is keyed (item_id, node_id, lot_id, state) and holds qty BIGINT, which is on-hand stock and is moved only by the movement ledger; available_qty BIGINT, maintained on the same row; and version. The declared invariant is available_qty = qty - SUM(allocation.qty) over that key in status held or committed, enforced by CHECK (available_qty >= 0) and CHECK (available_qty <= qty). allocation holds allocation_id, order_line_id, item_id, node_id, lot_id, qty, tier, status (held, committed, consumed, released, expired) and expires_at. Twelve allocator threads try to claim the last eight units of one item at one node inside the same 50 ms. Give the exact statements that let at most eight units be claimed, then say what changes if identical code runs under PostgreSQL REPEATABLE READ versus InnoDB REPEATABLE READ, and what a retried allocate for the same order line must do.
Approach
- Collapse the check and the write into one statement whose WHERE clause is the business rule: UPDATE inventory_position SET available_qty = available_qty - :q, version = version + 1 WHERE item_id = :i AND node_id = :n AND lot_id = :l AND state = 'on_hand' AND available_qty >= :q. qty is deliberately untouched: a hold is a promise, not a physical move, so only a movement may change on-hand and the ledger-equals-position invariant survives. Rowcount zero is a refusal, not an error, and the allocation row is inserted in the same transaction only when the rowcount is one.
- If the deployment carries no available_qty column and availability must be derived, the alternative is SELECT ... FOR UPDATE on the position row followed by the SUM over held and committed allocations inside the same transaction. That is correct but holds the row lock for two statements instead of one, which matters on a key taking hundreds of writes a second.
- Isolation is not a substitute for the atomic step, and it changes the error contract. Under PostgreSQL READ COMMITTED the losing UPDATE blocks, then re-evaluates its predicate against the newly committed row version and returns rowcount 0, which the handler already handles. Under PostgreSQL REPEATABLE READ the same statement instead raises SQLSTATE 40001 and the whole transaction must be retried, so a handler that only tests rowcount fails closed on an exception it never expected. InnoDB REPEATABLE READ does neither: a locking read or UPDATE performs a current read of the latest committed row, so the loser blocks and then sees rowcount 0, with a deadlock rather than a serialization failure as its exceptional case.
- Make the retry a no-op with a partial unique index: UNIQUE (order_line_id, node_id, lot_id) WHERE status IN ('held','committed'). Then a retried allocate conflicts instead of double-claiming, and the handler reads the existing allocation and returns it.
- Never source the availability number from a replica or a cache for this path. Replication lag is largest during the write burst that made the key hot, so the guarantee fails precisely when it is load-bearing.
- For the hottest item-node pairs, shed load without overselling: route allocations for that key through a single writer with a bounded queue and refuse with a conservative not-available when the queue is full. Splitting the position into N sub-rows cuts contention N-fold but strands the remainder across sub-rows and produces false out-of-stock when the last units are spread thin.
Worked solution 30 min
- Write the conditional UPDATE, the rowcount branch and the allocation INSERT, plus the partial unique index DDL and the two CHECK constraints the invariant needs.
- Set a position to qty = 8 and available_qty = 8, launch 12 threads each claiming 1, and assert exactly 8 succeed, available_qty lands at 0 and qty is still 8.
- Re-run the same race under PostgreSQL REPEATABLE READ and record how many transactions fail with 40001 rather than returning rowcount 0.
- Send one allocate twice for the same order line and node, and assert one allocation row and the same allocation_id returned both times.
- Remove the available_qty >= :q predicate and confirm CHECK (available_qty >= 0) aborts the losing transactions, proving the test exercises the race rather than serialising by luck.
Follow-up
- One order line needs two units from two different nodes, atomically. What do you do when those positions live in different shards and no distributed transaction is available?
- Soft-tier allocations expire. Show the sweeper statement, and say what stops it from releasing an allocation that is being committed at that instant.
- Under sustained contention your CAS retries. What is the retry budget, and what does the caller see when it is exhausted?
Fold late, out-of-order scan events into one status per leg
observation_event holds event_id, subject_type, subject_id, observed_status, occurred_at, received_at, dedupe_key (UNIQUE) and processing_status. A lookup table maps observed_status to status_rank SMALLINT along a progress lattice. Write one query returning the current status of every shipment leg that received an event in the last hour, such that a picked_up event arriving after a delivered event never changes the answer. Then explain exactly which part of your ordering makes a shuffled replay of the same batch produce identical output.
Approach
- Separate the two jobs. Deduplication is the UNIQUE on dedupe_key at ingest, because partner feeds resend whole windows; ordering is the fold. Either alone leaves a defect: dedupe without a lattice still lets a stale event win, and a lattice without dedupe double-counts a replayed window in anything that aggregates.
- Select the affected legs in one CTE by received_at >= now() - interval '1 hour', then fold over every event for those legs, not only the recent ones. Restricting the fold's input to the recent window is the failure: a lone late picked_up would be the only row considered and the leg would regress.
- Fold as a maximum over the lattice: SELECT DISTINCT ON (subject_id) subject_id, observed_status FROM ... ORDER BY subject_id, status_rank DESC, occurred_at DESC, event_id DESC. The equivalent form is ROW_NUMBER() OVER (PARTITION BY subject_id ORDER BY status_rank DESC, occurred_at DESC, event_id DESC) = 1.
- The determinism comes from the final event_id tiebreak. Rank and occurred_at alone leave two equal-rank events at the same instant to be resolved by heap order, which changes when rows are re-inserted, so the shuffled replay differs in exactly the cases nobody tests. With a total order over the tuple the fold is a max, which is commutative and associative and therefore order-insensitive.
- Do not advance a leg on occurred_at alone. The timestamp is device-reported and can be wrong, which is why the lattice rank leads the ORDER BY and why clock_offset_ms is worth storing: a future-dated event with a low rank then cannot promote itself past a delivered.
- Keep superseded rows and mark processing_status = 'superseded' rather than deleting them. The discarded event is usually the one that explains a delivery dispute, and deleting it makes the trace unanswerable.
Follow-up
- An event arrives a week late for a leg that is already invoiced. Does the fold apply it, reject it as late, or apply it and emit a correction?
- The stream is partitioned by source_id rather than by subject_id. What ordering guarantee do you actually have, and what breaks?
- How would you materialise this fold so the customer-facing status read is not running a window function per request?
What is your understanding of Lean Manufacturing principles and techni…
What is your understanding of Lean Manufacturing principles and techniques?
Approach
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
What are your thoughts on cloud compute and security in an industrial …
What are your thoughts on cloud compute and security in an industrial context?
Approach
- Clarify what is being asked and what a complete answer contains.
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Keep a distribution centre picking through a six-hour WAN outage
A site's link to the rest of the system fails for six hours mid-shift. The Warehouse Execution Service runs on site and holds the work already released to it; the Availability Service, the Fulfilment Orchestrator and every other node are on the far side of the partition. Decide what the floor may keep doing, what central sourcing may promise from that node meanwhile, and how buffered movements and a cycle count taken during the outage are reconciled on reconnect. Name the invariant you relax and for how long.
Approach
- Name both sides and what each still knows. The site holds released work with hard allocations and can still generate movements; it cannot see new demand or any other node. Central holds demand and the ledger but is blind to picks. The relaxed invariant is the freshness of that node's derived position, bounded by the outage. Conservation itself is not relaxed: movements are durable locally with their idempotency keys and will be applied exactly once on replay.
- Let the floor continue, but only on work already released. Buffer movements to local durable storage in occurred_at order, each carrying its idempotency_key, the device clock offset and the reference that caused it. The floor stopping costs labour immediately and visibly, while a six-hour-stale record costs promise accuracy that can be bounded on the other side - so the trade is worth making, and stating that reasoning is the answer, not the choice itself.
- Bound central's exposure instead of pretending it has data. After a staleness threshold, freeze that node's available quantity at last-known on_hand minus everything already released to it; after a longer threshold, drop the node out of sourcing entirely. The error direction is under-promising: a missed sale rather than a short ship, a re-source and a second shipment's freight.
- Defend against the real hazard, which is the double ship. Central will want to re-source a line the site is actively picking. Make a released line's hard allocation unexpiring and require an acknowledged cancel from the site before re-sourcing; with the site unreachable no ack is possible, so the line stays with the site and is re-sourced only after reconnect confirms it unpicked. An allocation expiry sweeper that fires during a partition is precisely how two trucks leave with the same unit.
- Write the reconnect protocol as an order, not a hope: replay buffered movements by occurred_at with their idempotency keys, so a replay attempted twice is a no-op; then run the reconciliation re-sum for that node bounded by each row's last_movement_id, so writes still in flight do not read as variances; then release allocations the site reports it never consumed; then re-enable the node for sourcing.
- Apply the cycle count as evidence, not as a command. Record counted_qty with its count time and derive the adjustment delta at apply time against the position as of that moment. Replaying a precomputed set-to-40 overwrites every pick that happened after the count was taken, which is the version of this mistake that survives review because the number looks authoritative.
Worked solution 40 min
- Draw the partition, list what each side can still read and write, and write the relaxed invariant as one sentence with an explicit time bound.
- Write the site buffer's record format and the exact fields a buffered movement must carry to be replayable months later.
- Write central's degradation rule: the frozen availability formula, both thresholds as numbers, and the direction of error with its cost on each side.
- Write the reconnect sequence in order, then work the count-versus-picks case concretely - a count of 40 at 14:10 followed by twelve picks before the link returns - and show the resulting position.
- State the residual damage the design accepts and the signal that detects it.
Follow-up
- The site's local buffer is lost during the outage. What is still recoverable, and from which records?
- Two sites partition at once and both were candidate sources for the same lines. What does sourcing do differently from the single-site case?
- How do you choose the two staleness thresholds, and what measurement tells you afterwards that they were wrong?
Cut-off misses and on-time drift after a clock rule change
Two reports arrive the same week. On the Sunday one region changed its UTC offset, 1,900 lines at nodes in that region were released an hour after the node's 17:00 local shipping cut-off and missed the trailer. Separately, on-time percentage for legs whose dest_zone differs from the origin's reads four points below the carrier's own figure, every week. promised_ship_at is a TIMESTAMPTZ computed at order creation, and on-time compares the delivery instant to the promised day in UTC. Find the single root cause and give the storage and comparison rules you would adopt.
Approach
- Test whether each symptom is zone-dependent before theorising. Group the cut-off misses by node time zone and by date: clustering on one date and one set of zones points at an offset rule, while a uniform spread across zones and dates would point at a scheduler delay. Group the on-time disputes by whether the UTC day and the dest_zone local day of the delivery instant differ; if every dispute falls inside that group, the comparison is the defect. The containment runs one way only: a leg delivered days early also has differing UTC and local dates and is on time under either rule, so the differing-dates group is much larger than the disputed set and finding members of it that are not disputed proves nothing.
- Re-derive the stored promise for the affected lines today and diff it against the stored value. A difference of exactly 3,600 seconds on rows created before the rule change is the signature of a future local time that was resolved to an instant at write time using the offset then in force. The instant did not move; the local wall time it represents did.
- State the distinction the fix rests on. Comparing two instants needs no zone at all, so if the promise really were an instant, on-time would be a plain comparison. The zone matters because both of these promises are statements about local wall time: a 17:00 cut-off at a node, and delivery within the promised local day at the stop.
- Adopt the storage rule by tense. A past event is an instant, so occurred_at, recorded_at, actual_depart_at and actual_arrive_at stay TIMESTAMPTZ. A future local policy is local wall time plus an IANA zone identifier resolved at read time, so the cut-off becomes (17:00, node.time_zone) and the promise carries promise_zone, which the schema already has. Evaluate on-time in the dest_zone local calendar.
- Handle duration arithmetic separately, because it breaks in the other direction. A leg departing 18:00 local and arriving 18:00 local the next day spans 23 elapsed hours across a spring-forward boundary and 25 across a fall-back, so planned transit must be expressed in one domain and converted deliberately rather than by subtracting instants and assuming 24.
- Close the ingestion hole and the deployment hole. Partner feeds that send a bare date with no zone must have the zone attached at ingestion from the node or stop, because it cannot be recovered later, and the tzdata version baked into the image must be refreshed on a schedule, since a stale database reproduces exactly this bug for a rule that changed after the image was built.
Follow-up
- Not every offset change is a whole hour and some zones sit at :30 or :45. Which parts of your fix assume an hour?
- A node in a zone that does not observe daylight saving ships to one that does. Where does the transit duration have to be computed?
- How do you backfill on-time for the last two quarters without restating figures that were already invoiced?
Roughly ninety minutes on weeknights with one longer weekend block. The plan cuts scope rather than compressing everything, on the assumption that one thing finished per night beats four half-started.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Fix the scope and take a cold baseline
- Read the role description and write the three things the loop will almost certainly test, then write an explicit not-doing list and keep it visible all week.
- Take one twenty-five-minute coding problem and one fifteen-minute design prompt cold, and write the single sentence naming what blocked each, because those two sentences decide where the remaining evenings go.
- Set the week's rule: one thing finished every night, including the night you only have forty minutes.
Deliverable: A one-page scope with a not-doing list and two cold attempts, each carrying one sentence on what blocked it.
Practice prompt ↗Practice prompt ↗Worked solution ↗02One pattern, written three times from blank
- Choose the single pattern most likely to appear in your loop and write it three times from an empty file rather than editing the previous attempt.
- On the third pass, write the invariant as a comment before the loop body and the complexity before the first line of code.
- Stop at ninety minutes even if the third version is imperfect, and write the one thing you would fix given another hour.
Deliverable: Three independent implementations of the same pattern plus a note on what changed between them.
Practice prompt ↗Practice prompt ↗03One design, only to the depth you can defend
- Take one system shape and go only as far as requirements, interface and data model, refusing to draw a box you could not survive a follow-up about.
- Attach one number to each non-functional requirement, deriving it rather than asserting it, and write the assumption the number rests on.
- Write the one tradeoff you are choosing against and the observation that would make you reverse it.
Deliverable: One design at interface-and-schema depth with derived numbers and one written reversible tradeoff.
Practice prompt ↗Practice prompt ↗04Only the fundamentals you will have to defend
- Write, in under two hundred words each, the answers to the two questions that follow almost any implementation: why this structure and not the obvious alternative, and what happens to this code at a hundred times the input.
- Write what an index actually costs: faster lookups on the indexed columns against a write that now maintains a second structure, plus the cases where the planner declines to use it anyway, low selectivity, or a predicate wrapping the column in a function.
- Delete any answer you cannot deliver aloud in under a minute, since an answer that needs reading is not an answer you have.
Deliverable: Three written answers, each under two hundred words and each timed aloud.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Your own work, timed
- Write a ninety-second and a four-minute version of your main project and time both aloud rather than reading them.
- Prepare the two follow-ups that always come: what you would do differently, and how you knew it worked.
- Put one number in the first sentence and be ready to say exactly where it came from and what it excludes.
Deliverable: Two timed narratives with one defensible number in the opening line.
Practice prompt ↗Practice prompt ↗06The one full rehearsal, in the weekend block
- Run a sixty-minute mock covering a coding round and a design round in one sitting with no break, because sustained attention is the thing evenings have not trained.
- Immediately afterwards, and before hearing any feedback, write the three moments you lost the thread.
- Spend the rest of the block only on those three moments, and on nothing you merely feel shaky about.
Deliverable: Mock notes naming three failure moments with a specific fix written under each.
Practice prompt ↗Practice prompt ↗07Taper
- Write the twenty-minute warm-up you will actually do on the morning: one problem you can already solve from a blank file, one design you can narrate, and nothing you have never seen.
- Re-read only your own notes from this week and open no new material.
- Write the logistics down: the editor or shared document you will be working in, whether execution and lookups are permitted, and the sentence you will use when you do not know something.
Deliverable: A one-page card holding the design structure, the project numbers, and the logistics.
Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Team size, service count and tickets closed say very little. Seniority shows in the decision you owned: what you chose not to build, which constraint you traded away, whose objection you had to resolve before anything could move. A large project where you executed someone else's plan is a small story.
Which of the Terex Corporation values resonate with you most and why?
Which of the Terex Corporation values resonate with you most and why?
Approach
- Close with what you would do differently, concretely.
- State the situation in two sentences and spend the rest on the reasoning.
- Pick a story where you made the decision, not one where you watched it.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Why do you want to work at Terex Corporation?
Why do you want to work at Terex Corporation?
Approach
- Pick a story where you made the decision, not one where you watched it.
- Name the disagreement and how you resolved it with evidence.
- State the situation in two sentences and spend the rest on the reasoning.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Can you explain your experience with hydraulic systems and electrical …
Can you explain your experience with hydraulic systems and electrical circuits?
Approach
- Close with what you would do differently, concretely.
- Pick a story where you made the decision, not one where you watched it.
- Give the blast radius: what could have broken, and what you measured.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Where do you see yourself in 3–5 years?
Where do you see yourself in 3–5 years?
Approach
- Name the disagreement and how you resolved it with evidence.
- Give the blast radius: what could have broken, and what you measured.
- Close with what you would do differently, concretely.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
- 01
Which of the Terex Corporation values resonate with you most and why?
- 02
Why do you want to work at Terex Corporation?
- 03
Can you explain your experience with hydraulic systems and electrical circuits?
- 04
Where do you see yourself in 3–5 years?
Is this an official Terex Corporation interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Terex Corporation. Rounds and questions reflect what candidates have reported, not a process Terex Corporation has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How much preparation time is typical?
Candidates typically spend a few days researching Terex Corporation products and reviewing their own project history. Focus on being able to explain the "why" and "how" behind your past technical decisions.
PracHub interview research ↗What differentiates successful candidates?
The most successful candidates are those who show genuine interest in Terex Corporation's products and can bridge the gap between abstract software solutions and physical, industrial applications.
PracHub interview research ↗What is the working style at Terex Corporation?
Candidates report an emphasis on collaboration and hands-on problem solving. You will often work alongside engineers from other disciplines, so being able to communicate across departments is essential.
PracHub interview research ↗How long does the process take?
While timelines vary by location, the process generally moves from a phone screen to a panel or onsite interview within a few weeks.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22