A Software Engineer at Sound Transit plays a critical role in building, maintaining, and optimizing the digital infrastructure that keeps the Puget Sound region moving. Unlike traditional technology companies focused on commercial software, engineers here work at the intersection of physical infrastructure, public service, and real-time systems. The software and systems you design and support directly impact millions of passengers who rely on Link light rail, Sounder trains, and regional express buses every day. In this role, you will contribute to complex problem spaces ranging from transit scheduling and Network Operations Center (NOC) systems to train-board electronics, fire protection integration, and public-facing informational displays. Your work ensures that transit operations are safe, efficient, and equitable. It is a highly collaborative environment where software engineering meets systems engineering, requiring a deep understanding of how digital solutions integrate with physical transit assets. For engineers who want their code to have a tangible, positive impact on the community and the environment, offers a unique and rewarding mission. You will face complex engineering challenges around system reliability, real-time data processing, and cross-departmental integration, making this position both technically challenging and socially impactful. Sound Transit
Initial Screening Call
reportedA call with Human Resources to discuss your background, salary expectations, and benefits.
What to demonstrate
- A call with Human Resources to discuss your background, salary expectations, and benefits
- Depth in Systems Thinking (Domain/System Overview)
How to prepare
- Be able to walk your CV end to end in two minutes, and say why this company specifically.
- Have your salary expectations, notice period and location constraints ready, and ask for the rest of the loop in writing.
Structured Panel Interview
reportedThe core evaluation process involving a panel interview to assess technical skills and fit.
What to demonstrate
- The core evaluation process involving a panel interview to assess technical skills and fit
- Depth in Systems Thinking (Domain/System Overview)
How to prepare
- Answer aloud and timed: How do you handle communication challenges when working with stakeholders from different departments or non-technical backgrounds?
- Answer aloud and timed: Tell me about a time when a project did not go as planned. What did you learn, and how did you adapt?
Second-Round Interview
reportedFor senior or specialized roles, a second interview with department directors and cross-functional colleagues may occur.
What to demonstrate
- For senior or specialized roles, a second interview with department directors and cross-functional colleagues may occur
- Depth in Systems Thinking (Domain/System Overview)
How to prepare
- Answer aloud and timed: Why should we hire you for this position, and why are you interested in working for Sound Transit?
- Answer aloud and timed: Talk about the systems on a train. How do you think they communicate with each other and with central operations?
On-Site Visit or Reference Questionnaires
reportedSome roles may require an on-site visit or completion of reference questionnaires.
What to demonstrate
- Some roles may require an on-site visit or completion of reference questionnaires
- Depth in Systems Thinking (Domain/System Overview)
How to prepare
- Answer aloud and timed: How would you approach designing or optimizing a system designed for a Network Operations Center (NOC)?
- Answer aloud and timed: How do you ensure high availability and safety in software systems that interface with physical infrastructure?
PracHub editorial advice for the preparation topics above.
Master the STAR Method
Every behavioral question should be answered with a clear Situation, Task, Action, and Result. Focus heavily on your personal contribution (use "I" instead of "we").
Study the Agency's Mission
Familiarize yourself with Sound Transit's current expansion plans, such as the ongoing Link light rail expansions. Understanding the agency's growth will help you articulate why you want to join.
Sound Transit is a mission-driven public agency
Aligning your answers with their core values of safety, equity, and environmental sustainability will significantly boost your candidacy.
Prepare for Structured Panels
Do not expect a casual, conversational back-and-forth during the panel interview. Panels often read questions verbatim to ensure compliance with public hiring guidelines. Stay confident and deliver complete, self-contained answers.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Archive a resource graph without breaking live references or recursing
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?
Find overlapping job attempts and peak concurrency from lease records
A day of job_run history yields about 50,000,000 attempt records: (job_run_id, job_type, attempt, started_at, finished_at which is NULL when the worker died, lease_expires_at). Leases expire on a clock, so a job that outran its lease ran twice. Produce (a) every job_run_id whose attempts overlapped in wall-clock time and (b) the peak number of simultaneously running attempts per job_type with the minute it occurred. Target O(n log n). State how you treat a NULL finished_at and what clock skew does to your answer.
Approach
- Define the interval before sorting anything: an attempt occupies [started_at, COALESCE(finished_at, lease_expires_at)). finished_at is observed and lease_expires_at is only a promise, so every attempt without a finish contributes an estimate and the whole result is a lower bound on overlap rather than an exact count.
- For peak concurrency, sweep: emit 2n endpoints, sort by (timestamp, kind) with ends ordered before starts at equal timestamps, then walk the sequence maintaining a counter per job_type and record each type's maximum with its timestamp. O(n log n) dominated by the sort, O(n) space, or O(1) extra if the sort is external and the walk streams.
- For overlap detection, do not compare attempts pairwise. A single global sort by (job_run_id, started_at) gives both the grouping and the order; within a group, keep the maximum end seen so far and report an overlap exactly when the next start is less than that running maximum, which is one linear pass after the sort.
- Half-open intervals matter and are easy to get wrong: with closed intervals an attempt ending at the same millisecond another begins reads as concurrency two, and across 50,000,000 records that artefact swamps the real signal.
Follow-up
- A handler is not idempotent and you have found 400 overlapping jobs. Which of them actually caused damage, and what would you query to find out?
- Peak concurrency for one job_type is 4 against a configured cap of 4. Is the cap working, or is the data hiding attempts that never started?
Diff a projection against the primary without per-row point reads
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
- 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.
- 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.
- 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.
- 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?
Stop tag and share joins from fanning out a page
resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.
Approach
- Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
- Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
- Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
- Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.
Follow-up
- The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
- A resource can be shared with the same user twice under different permissions. Does your count change, and should it?
Find version gaps and relay lag with window functions
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?
Talk about the systems on a train. How do you think they communicate with each other and with central operatio
Talk about the systems on a train. How do you think they communicate with each other and with central operations?
Approach
- Clarify what is being asked and what a complete answer contains.
- 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
- What assumption would you test first?
- How would you know your answer was wrong?
How would you approach designing or optimizing a system designed for a Network Operations Center (NOC)?
How would you approach designing or optimizing a system designed for a Network Operations Center (NOC)?
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
How do you ensure high availability and safety in software systems that interface with physical infrastructure
How do you ensure high availability and safety in software systems that interface with physical infrastructure?
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Exports duplicate a row range about once a week
Roughly once a week an export writes a file containing a duplicated range of rows. The affected job_run rows show attempt = 1, status = succeeded, one started_at, and a lease_owner naming a different host from the one whose logs show the job starting. Leases last 30 seconds and are heartbeated every 10 from inside the handler; lease_expires_at is computed on the worker and compared against the database's now(). Find the mechanism, and give a fix that holds even if you cannot fix the clocks.
Approach
- Start from the fact that eliminates the obvious answer. attempt = 1 means no retry was recorded, so this is not a re-run after failure; two workers ran the same row concurrently and the takeover path never touched the counter. lease_owner naming a host other than the one that started the job is the same statement from the other side.
- Enumerate the mechanisms that cause a premature takeover, then find the signal that separates them. Either the lease genuinely expired because the heartbeat did not fire, which is what happens when the heartbeat runs on the handler's own thread and the handler makes a long blocking call, or it only appeared expired because two clocks disagree, since lease_expires_at is written from the worker's clock and evaluated against the database's. The discriminator is the distribution: incidents clustered on the longest exports indict the heartbeat, incidents clustered on one host indict skew. Measure both, and measure each host's offset against the database directly.
- Read the reclaim query precisely. In PostgreSQL now() is transaction start time, not statement time, so a reclaimer holding a long transaction compares against an older timestamp than expected; clock_timestamp() is the statement-time function. This is worth ruling in or out before you redesign anything, because it changes which rows look expired.
- Remove the second clock rather than trying to synchronise it. Issue and extend the lease in the database, with lease_expires_at = now() + interval '30 seconds' in both the claim and the heartbeat, so exactly one clock is ever compared and worker skew stops mattering to this predicate.
Follow-up
- The displaced worker has already streamed half the file to object storage. What makes that side effect safe to repeat?
- You now count takeovers. What alert fires on that counter, and at what threshold?
Built from the rounds and topics Sound Transit candidates report.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the Sound Transit loop
- Write out the reported sequence: Initial Screening Call, Structured Panel Interview, Second-Round Interview, On-Site Visit or Reference Questionnaires.
- For each round, write one sentence on what it is judging, from the description above, and mark the one you are least ready for.
Deliverable: A one-page map of the 4 reported rounds, with the weakest marked.
02Work Systems Thinking (Domain/System Overview)
- Spend the session on Systems Thinking (Domain/System Overview), which Sound Transit candidates report being tested on.
- Write one worked example in Systems Thinking (Domain/System Overview) and time yourself on it.
Deliverable: One timed worked example in Systems Thinking (Domain/System Overview).
03Work Communication Skills
- Spend the session on Communication Skills, which Sound Transit candidates report being tested on.
- Write one worked example in Communication Skills and time yourself on it.
Deliverable: One timed worked example in Communication Skills.
04Work Clarifying Requirements / Handling Ambiguous Questions
- Spend the session on Clarifying Requirements / Handling Ambiguous Questions, which Sound Transit candidates report being tested on.
- Write one worked example in Clarifying Requirements / Handling Ambiguous Questions and time yourself on it.
Deliverable: One timed worked example in Clarifying Requirements / Handling Ambiguous Questions.
05Answer out loud: Behavioral & Scenario-Based Questions
- Answer aloud, timed: Talk about a past project you worked on, focusing on your specific contributions and the ultimate outcome.
- Answer aloud, timed: Describe a time when you had to complete a task with highly unclear or ambiguous instructions. How did you proceed?
Deliverable: Spoken answers to 2 reported Behavioral & Scenario-Based Questions question(s), under time.
06Answer out loud: Transit Systems & Domain-Specific Questions
- Answer aloud, timed: Talk about the systems on a train. How do you think they communicate with each other and with central operations?
- Answer aloud, timed: How would you approach designing or optimizing a system designed for a Network Operations Center (NOC)?
Deliverable: Spoken answers to 2 reported Transit Systems & Domain-Specific Questions question(s), under time.
07Answer out loud: Equity & Values Questions
- Answer aloud, timed: How do you contribute to equity, diversity, and inclusion in your professional work and team interactions?
- Answer aloud, timed: What does public service mean to you, and how does it influence your approach to engineering?
Deliverable: Spoken answers to 2 reported Equity & Values Questions question(s), under time.
Expand any day for tasks and deliverables. Your progress is saved on this device.
Behavioural rounds judge the decision you made and what it cost.
Talk about a past project you worked on, focusing on your specific contributions and the ultimate outcome.
Talk about a past project you worked on, focusing on your specific contributions and the ultimate outcome.
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Describe a time when you had to complete a task with highly unclear or ambiguous instructions. How did you pro
Describe a time when you had to complete a task with highly unclear or ambiguous instructions. How did you proceed?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
How do you handle communication challenges when working with stakeholders from different departments or non-te
How do you handle communication challenges when working with stakeholders from different departments or non-technical backgrounds?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Tell me about a time when a project did not go as planned. What did you learn, and how did you adapt?
Tell me about a time when a project did not go as planned. What did you learn, and how did you adapt?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Why should we hire you for this position, and why are you interested in working for Sound Transit?
Why should we hire you for this position, and why are you interested in working for Sound Transit?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
How do you contribute to equity, diversity, and inclusion in your professional work and team interactions?
How do you contribute to equity, diversity, and inclusion in your professional work and team interactions?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
What does public service mean to you, and how does it influence your approach to engineering?
What does public service mean to you, and how does it influence your approach to engineering?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
- 01
Talk about a past project you worked on, focusing on your specific contributions and the ultimate outcome.
- 02
Describe a time when you had to complete a task with highly unclear or ambiguous instructions. How did you proceed?
- 03
How do you handle communication challenges when working with stakeholders from different departments or non-technical backgrounds?
- 04
Tell me about a time when a project did not go as planned. What did you learn, and how did you adapt?
How technical is the Software Engineer interview at Sound Transit?
The interview focuses heavily on systems thinking, operational logic, and behavioral competency rather than highly abstract algorithmic coding challenges (like LeetCode hard questions). Be prepared to discuss system architecture, data flow, and real-world project execution.
Sound Transit Software Engineer candidate reports ↗What is the panel interview like?
The panel typically consists of four team members, including the hiring manager and potential peers. They will take turns asking structured questions. The format is formal to ensure fairness, so focus on delivering clear, structured answers using the STAR method.
Sound Transit Software Engineer candidate reports ↗How long does the hiring process take?
Because Sound Transit is a public agency, the hiring process can take several weeks to a few months from application to offer. There may be periods of silence between rounds as background checks, reference questionnaires, and internal approvals are processed.
Sound Transit Software Engineer candidate reports ↗Does Sound Transit offer remote or hybrid work?
Most software and systems engineering roles offer a hybrid work model, allowing a mix of remote work and in-office collaboration at the Seattle headquarters, depending on operational and team needs.
Sound Transit Software Engineer candidate reports ↗What topics does Sound Transit test in interviews?
Sound Transit interviews most often cover Project Management, STAR Method, Stakeholder Management, Security Architecture, and Program Management. The exact emphasis depends on the specific role you apply for.
Sound Transit Software Engineer candidate reports ↗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.
- 01Sound Transit Software Engineer candidate reports ↗
Company-reported rounds, questions and FAQ.
Candidate reports · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
PracHub practice material, not company-reported.
PracHub page · Accessed 2026-09-22 - 03PracHub preparation framework ↗
PracHub preparation guidance.
PracHub page · Accessed 2026-09-22