Goldman Sachs Interview Questions · 2026

Goldman Sachs Interview Questions (2026): What They Actually Ask

When a backend engineer with four years of Java and distributed systems experience applied to Goldman Sachs' technology division in late 2024, the recruiter gave him one piece of advice: "Don't prep like you're interviewing at a pure tech company." She was right. The coding problems were LeetCode medium. The thing that actually filtered candidates was whether they could reason about financial systems constraints, auditability, fault tolerance, regulatory compliance, and correctness under load, on top of a DSA foundation.

Goldman's technology interview has a reputation for being harder to read than Google or Meta. It's not a pure LeetCode shop, but it's not a system design marathon either. What it runs is a multi-stage filter that starts with a HackerRank online assessment, moves through live CoderPad technical screens, and ends with a Superday of three to five back-to-back rounds covering DSA, system design, low-level design, and behavioral questions tied directly to the firm's 14 Business Principles. This page covers what that process actually looks like in 2025 and 2026, based on verified candidate reports from Glassdoor, GeeksForGeeks, TechPrep, and Medium write-ups from engineers who went through it.

6-10 weeksProcess
5-7Rounds
LC MediumCoding
HackerRank + CoderPad + SuperdayFormat

How the Goldman Sachs interview works in 2026

The full process from application to verbal offer typically runs six to ten weeks. Campus and referral tracks can compress to four to six weeks. The most common complaint candidates report is long waits between stages, sometimes two weeks between the Superday and feedback, so plan for it.

HackerRank online assessment90-135 min

The first gate for engineering roles. Format varies by program and region, but the standard version includes two to three coding problems at medium difficulty, plus multiple-choice questions covering CS fundamentals, quantitative aptitude, and sometimes a short written component. The proctored test allows C, C++, Java, Python, and Scala. Candidates who score below threshold don't advance. Goldman reportedly does a resume review before sending OA links, so it's not a mass-volume screener the way some firms run it.

Recruiter screen20-30 min

A short call covering background, motivation, and compensation expectations. The recruiter will often indicate which technical areas to focus on for the loop (DSA, system design, LLD) depending on the target team and seniority level. This is also a good moment to ask whether the CoderPad round will include low-level design, as the answer varies by team.

CoderPad technical screen45-75 min

Live coding with a Goldman engineer. A brief resume discussion comes first (usually 10 minutes), followed by one to two coding problems where you must produce working, runnable code. Interviewers at this stage pay attention to how you communicate your approach before writing, not just whether you arrive at a solution. For candidates with three or more years of experience, this round sometimes includes a short LLD component.

Superday3-5 rounds, 45-60 min each

All rounds happen on the same day, back to back. Standard Superday for SWE roles includes a DSA round, a system design or HLD round, a low-level design round, and a behavioral round. Some teams add a fifth round with a managing director, which is more conversational but can still include surprise technical questions. Virtual format has been standard since 2021 and continued through 2025 and 2026 for most technology roles.

One structural detail worth knowing: Goldman uses a "one passing team" rule at the Superday stage. If you perform well in a round with a particular team, that team can advance you even if another team's interviewers have concerns. It's not a purely aggregated score system. This matters because performing very well with one interviewer can carry you forward even if a round goes poorly.

Easy questions

19

The OA is proctored, usually with webcam and screen recording enabled for the full session. Beyond the two or three coding problems, most candidates report a multiple-choice section covering CS fundamentals (OOP concepts, data structure complexity, basic operating systems and networking) and quantitative aptitude items closer to a campus placement test than a coding interview. Graders award partial credit for test cases a solution passes, even if the full problem isn't solved, so a partially working submission beats a blank editor.

Reported consistently across recent HackerRank OA experiences: the MCQ section carries real weight toward the pass/fail threshold, and candidates who spend all their time polishing the coding half sometimes fail on the aggregate score anyway. Answering every multiple-choice item, even by elimination, is usually worth more than another ten minutes chasing a stubborn edge case on a solution that already passes most test cases.

Two-pointer or single-pass approach. Track the current character and a count. When the character changes, append the previous character and count to the result. The key edge case is the final group, which doesn't trigger a character change. Append it after the loop ends.

Reported in a 2024 CoderPad screen from a candidate with three years of experience. The follow-up was whether this handles Unicode characters correctly (yes, if you treat them as single code points) and how you'd decode the compressed string back.

java
public String compress(String s) {
    if (s == null || s.isEmpty()) return s;
    StringBuilder sb = new StringBuilder();
    int count = 1;
    for (int i = 1; i <= s.length(); i++) {
        if (i < s.length() && s.charAt(i) == s.charAt(i - 1)) {
            count++;
        } else {
            sb.append(s.charAt(i - 1));
            sb.append(count);
            count = 1;
        }
    }
    return sb.toString();
}

Fill from the back of the first array (which has extra space) using two pointers starting at the last real element of each array. Compare and place the larger value at the current tail position, then move that pointer left. This avoids shifting elements forward.

Reported across multiple CoderPad phone screens as a warm-up question. Candidates who start filling from the front and then realize they're overwriting elements lose time recovering. Always clarify whether "in-place" means no extra arrays or truly O(1) extra memory.

Single pass to build a frequency map, then a second pass to find the first character with frequency 1. O(n) time, O(1) space since the character set is bounded. Using LinkedHashMap in Java preserves insertion order and can reduce the second pass.

Reported directly from a Goldman Sachs Round 2 experience published September 2024 on GeeksForGeeks. Interviewers follow up by asking how you'd handle a stream of characters where you need to report the first unique character after every insertion.

Push every opening bracket onto a stack. On a closing bracket, pop the stack and confirm the popped bracket matches the expected opening type. If the stack is empty when a closing bracket arrives, or a mismatch occurs, the string is invalid. The string is only valid if the stack is empty once every character has been processed.

Reported as a common warm-up in the CoderPad screen, usually as the first of two problems before something harder. The trap candidates fall into is forgetting the final check: a string like "(((" passes every individual character comparison but leaves unmatched brackets on the stack, so it must still be rejected.

Iterative: keep three pointers, prev, curr, and next. At each node, save curr.next, point curr.next back to prev, then advance prev and curr. Recursive: base case is null or a single node; recurse on curr.next first, then set curr.next.next = curr and curr.next = null on the way back up the call stack.

One of the most commonly reported opening questions in the live Superday DSA round precisely because it's fast enough to finish in a few minutes, which leaves room for the interviewer to ask you to reverse only a sub-section of the list (say, positions m through n). That follow-up trips up candidates who memorized the full-list version without understanding the pointer mechanics underneath it.

java
ListNode reverse(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

A derivative is a financial contract whose value is derived from an underlying asset, index, or rate. Options, futures, swaps, and forwards are the four main types. A stock option gives the holder the right (but not the obligation) to buy or sell a stock at a predetermined price (the strike) by a certain date. Goldman technology engineers working on trading systems, risk, or pricing engines will encounter derivatives constantly. You don't need to know options pricing theory at interview level, but knowing the vocabulary signals domain awareness.

Interviewers often follow up with: "If you were building the data schema for storing options contracts, what fields would you need?" That's where domain knowledge becomes an engineering problem. Fields: underlying symbol, strike price, expiry date, contract type (call/put), contract size, premium at time of purchase, and current mark-to-market value.

T+1 means a trade settles one business day after the trade date. The US moved from T+2 to T+1 settlement in May 2024. From a systems perspective, this means your risk and settlement systems must process all the trade data, matching confirmations, and position updates within a much tighter window. It puts real engineering pressure on end-of-day batch jobs and near-real-time pipelines. Goldman's controllers team, for example, needs to reconcile all trades and positions before the next market open.

If you're interviewing for any role touching trade lifecycle, clearing, or settlement, knowing that the US moved to T+1 in May 2024 is a specific data point that signals you follow industry developments. Most candidates from pure tech backgrounds have never heard of it.

The answer is a quarter and a nickel. The trick is the wording: "one of them is not a nickel." The statement says one of them is not a nickel, which is true: the quarter is not a nickel. The other one is. Goldman brain teasers test whether you read precisely and resist the urge to over-constrain based on an implied reading.

This style of question appears in earlier-stage Goldman interviews (HireVue or recruiter screen) more than in technical rounds. The broader lesson for finance interviews: read the problem statement carefully before committing to an interpretation.

Stocks are equity: holders own a fractional claim on the company's future earnings and assets, with no guaranteed return. Bonds are debt: holders lend money to the issuer at a fixed or floating interest rate, with a defined repayment schedule. Bonds are senior to equity in a bankruptcy, so they carry lower default risk, but they also cap upside. For a software engineer building a portfolio risk system at Goldman, this matters because you need to model equity and fixed-income positions differently: stocks use volatility and beta; bonds use duration, yield, and credit spread. The data schemas and pricing models are distinct.

This opens nearly every stage of the Goldman loop: the recruiter screen, the intro minutes of the CoderPad round, and the first Superday round of the day. A tight answer runs 60 to 90 seconds and moves present to past to future: what you do now and what you own, the one or two prior experiences that explain why you're a fit for this specific team, then why you're looking at Goldman right now. Skip reciting the resume line by line; the interviewer already has it open in front of them.

Reported as the opening question at almost every stage of the process, which means candidates often answer it three or four separate times across a single loop and get sloppy by the third repetition. Interviewers notice the difference between an answer that sounds word-for-word rehearsed and one where the candidate has adjusted the emphasis to match what that specific interviewer's team actually builds.

This question is asked at nearly every Goldman technology loop and has a high failure rate for candidates who prep only for LeetCode. Generic answers about "impact" or "scale" land flat. The interviewers want specificity: a product Goldman ships, a market condition that creates an interesting engineering challenge, or a specific technical problem (real-time settlement under T+1, risk aggregation at microsecond latency) that you've thought about. Do your homework on what the target team actually builds before the Superday.

The best answers connect a genuine engineering interest to something Goldman uniquely does. "I'm interested in low-latency event-driven systems and Goldman's work on real-time trade processing under T+1 settlement constraints is the most interesting applied version of that problem I've seen" is specific. "I want to work at a prestigious firm that uses technology" is not.

Be concrete about what you deferred and what it cost. "We shipped without full error handling to meet a regulatory reporting deadline, then spent the next sprint adding it, and we did catch one edge case during that cleanup that would have been a data quality issue in production" is the kind of specific, honest answer that lands. Vague answers ("I always try to balance both") signal that you haven't made a real trade-off deliberately.

Goldman interviewers follow up by asking whether that was the right call given what you know now. Have a real answer. Trade-offs that didn't work out perfectly are more credible and interesting than stories where every decision was optimal.

Most candidates report six to ten weeks from application to verbal offer. Campus hires and referrals can move in four to six weeks. The longest waits are typically between the CoderPad screen and Superday invitation (one to two weeks) and between the Superday completion and feedback (also one to two weeks). Goldman's HR teams are known for slow feedback turnaround. If you haven't heard back within two weeks of a round, a polite follow-up to your recruiter is appropriate.

The HackerRank OA accepts C, C++, Java 7/8, Python 2/3, and Scala. Goldman's internal technology stack is heavily Java, and some CoderPad rounds explicitly ask you to code in Java. Python is accepted for the OA and usually acceptable in the CoderPad screen, but if you know Java, using it signals familiarity with the firm's stack. For the Superday coding rounds, clarify with your recruiter whether language is constrained for your specific team.

For most SWE roles, no deep finance knowledge is tested. But the Superday behavioral round almost always includes "Why Goldman over a pure tech company?" which requires you to name something specific about Goldman's business or technical domain. System design rounds often use finance-domain scenarios (trade processing, payment systems, market data pipelines) and interviewers notice when candidates understand the financial constraints vs. when they don't. Reading up on T+1 settlement, what derivatives are, and the basics of trading systems is an hour of prep that most candidates skip and shouldn't.

The Superday is three to five back-to-back rounds on the same day, each 45 to 60 minutes. Standard composition for SWE: one DSA coding round, one system design or HLD round, one low-level design round, and one behavioral round. Some teams add a fifth round with a managing director, which is more conversational but can include surprise technical questions. The virtual format (video call) has been standard since 2021 and continues in 2025 and 2026 for most roles.

Very important for most technology roles. Goldman's core systems (trading, risk, settlement) are Java-heavy. CoderPad rounds may be language-flexible, but interviewers ask Java internals questions (HashMap implementation, thread pools, concurrency primitives) in Superday rounds regardless of what language you coded in. If you haven't used Java recently, spend time reviewing java.util.concurrent, HashMap internals, and Spring Boot basics. For roles explicitly labeled as Python or JavaScript, the Java requirement is lighter, but internals questions on those languages take its place.

Yes, for some programs and regions, particularly campus recruiting and certain analyst-track roles. The HireVue is a one-way recorded video interview with roughly 30 minutes total, about 30 seconds to prepare per question and two to three minutes to answer. Questions are behavioral and "Why Goldman?"-style. For experienced engineering hires, the HireVue is less commonly used and the CoderPad screen is more typical. Ask your recruiter which format applies to your specific role and location.

Medium questions

19

Two-pointer approach: maintain left and right pointers at the array boundaries, and left_max and right_max tracking the highest bar seen from each side. Move the pointer on the side with the lower max inward, adding the difference between the max and the current bar to the total water. This runs in O(n) time and O(1) space.

Reported from a 2024 CoderPad round and from multiple Superday coding rounds. The interviewers often ask candidates to first state the brute force O(n^2) approach and then optimize. Jumping straight to two pointers without explaining the precomputed-max approach first can raise questions about whether you understand why it works.

python
def trap(height):
    left, right = 0, len(height) - 1
    left_max = right_max = 0
    water = 0
    while left < right:
        if height[left] < height[right]:
            if height[left] >= left_max:
                left_max = height[left]
            else:
                water += left_max - height[left]
            left += 1
        else:
            if height[right] >= right_max:
                right_max = height[right]
            else:
                water += right_max - height[right]
            right -= 1
    return water

Backtracking with pruning. Place three dots in the string to create four segments. Each segment must be a number between 0 and 255, must not have leading zeros (unless the segment is "0" itself), and the remaining digits after placing a dot must be able to form valid remaining segments. Prune when a segment is invalid.

Reported from a Superday Round 4 in a 2024 SDE2 experience. The follow-up was whether you could generate all valid IPs in sorted order, which requires either sorting after generation or enforcing lexicographic ordering during backtracking.

python
def restoreIpAddresses(s):
    results = []

    def backtrack(start, parts):
        if len(parts) == 4 and start == len(s):
            results.append('.'.join(parts))
            return
        if len(parts) == 4 or start == len(s):
            return
        for length in range(1, 4):
            if start + length > len(s):
                break
            segment = s[start:start + length]
            if len(segment) > 1 and segment[0] == '0':
                break
            if int(segment) > 255:
                break
            backtrack(start + length, parts + [segment])

    backtrack(0, [])
    return results

Sort arrival and departure arrays separately. Use two pointers: advance through arrivals and departures in chronological order. When the next event is an arrival, increment the platform count. When it's a departure, decrement. Track the maximum count reached. This is a sweep-line approach and runs in O(n log n) due to sorting.

Reported in a September 2024 Goldman Sachs Superday from a candidate on the Controllers team. The financial framing is intentional: trade settlement windows create the same kind of resource-contention problem. Interviewers at Goldman ask this partly to see if you recognize the domain connection.

Union-Find or BFS/DFS from each unvisited node. For the "transitive relationships" variant, model each person as a node and each known-pair as an edge. Run BFS from every unvisited node, marking all reachable nodes as the same component. The number of BFS starts equals the number of connected components.

Reported from the same September 2024 Superday and from a 2025 SDE2 Superday Round 5. Goldman interviewers often ask what happens when you add a constraint that some relationships have a "strength" and you only want transitive connections above a threshold. That extends this into a weighted graph with minimum spanning tree thinking.

Sliding window with a hash map that stores the last seen index of each character. Expand the right pointer through the string. When the current character has already been seen inside the current window, jump the left pointer to one past its last seen index instead of moving it one step at a time. Track the max window length at each step. This runs in O(n) time with a single pass, since the left pointer only ever moves forward.

One of the most frequently reported coding questions across Goldman Sachs HackerRank and CoderPad rounds, showing up in candidate write-ups on GeeksForGeeks and LeetCode Discuss threads specifically tagged to the firm. The follow-up interviewers ask most often is whether the solution handles an empty string and repeated characters correctly, and whether you can avoid the extra hash map by using a fixed 128 or 256-size array for ASCII input.

python
def length_of_longest_substring(s):
    last_seen = {}
    left = 0
    max_len = 0
    for right, char in enumerate(s):
        if char in last_seen and last_seen[char] >= left:
            left = last_seen[char] + 1
        last_seen[char] = right
        max_len = max(max_len, right - left + 1)
    return max_len

Modified binary search. At each step, one half of the array (left of mid or right of mid) is guaranteed to be properly sorted, even though the array as a whole isn't. Check which half is sorted by comparing the endpoints to the mid value, then check whether the target falls inside that sorted half's range. If it does, search that half; otherwise search the other half. This preserves O(log n) time.

This shows up in Superday DSA rounds as a step up from plain binary search, since candidates first have to explain why a standard binary search breaks on a rotated array before writing the fix. The common follow-up asks you to handle duplicate values, which breaks the clean "which half is sorted" determination and can force a linear worst case in the degenerate all-duplicates input.

BFS or DFS from every unvisited land cell. Each traversal marks all four-directionally connected land cells as visited and counts as one island. Iterate over every grid cell; whenever an unvisited land cell is found, run a traversal from it and increment the island count once. Runs in O(rows x cols) time since every cell is visited at most once.

Reported in Superday rounds as the matrix-traversal companion to the graph connected-components question above. A frequent follow-up asks you to also report how many islands touch the grid's border versus how many are fully enclosed, which changes the approach to flood-fill inward from the border cells first and exclude anything reachable from them.

Floyd's tortoise and hare. A slow pointer advances one node at a time, a fast pointer advances two. If they meet, a cycle exists. To find where the cycle starts, reset one pointer to the head and advance both pointers one step at a time; the node where they meet next is the cycle's entry point. Runs in O(n) time and O(1) space.

Reported as a natural follow-up to the basic reverse-a-linked-list question in Superday rounds. Interviewers want you to justify why resetting one pointer to the head after the first meeting point actually finds the cycle start, not just recite that it works. Being able to derive the distance relationship on the whiteboard matters more than the code itself here.

BFS with a queue. Push the root, then loop while the queue isn't empty: record the current queue size as the count of nodes at this level, pop that many nodes, push each one's children, and append the popped values as one level in the result. This generalizes directly to the grid and graph BFS used elsewhere in the loop.

Reported in early Superday rounds as a check that you can implement BFS cleanly, not just describe it. The typical follow-up asks you to return the levels in zigzag order, alternating left-to-right and right-to-left on each level, which just means reversing every other level's list before appending it.

Core components: a fixed-size pool of worker Thread objects, a BlockingQueue as the task queue (ArrayBlockingQueue with a capacity limit), and a Runnable wrapping each incoming request. Worker threads loop on queue.take(), blocking when empty. On shutdown, drain the queue and interrupt workers. ThreadPoolExecutor from java.util.concurrent is the production answer, but interviewers want you to sketch the mechanics from scratch before reaching for it.

Reported from a 2025 Superday Round 5 involving thread-safety questions. The follow-up: what happens when the queue is full and a new request arrives? Options are reject (throw RejectedExecutionException), block the caller, or drop the oldest task. Goldman interviewers want you to name the trade-off, not just pick one.

java
import java.util.concurrent.*;

class SimpleThreadPool {
    private final BlockingQueue<Runnable> taskQueue;
    private final Thread[] workers;
    private volatile boolean shutdown = false;

    SimpleThreadPool(int poolSize, int queueCapacity) {
        taskQueue = new ArrayBlockingQueue<>(queueCapacity);
        workers = new Thread[poolSize];
        for (int i = 0; i < poolSize; i++) {
            workers[i] = new Thread(() -> {
                while (!shutdown || !taskQueue.isEmpty()) {
                    try {
                        Runnable task = taskQueue.poll(100, TimeUnit.MILLISECONDS);
                        if (task != null) task.run();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
            workers[i].start();
        }
    }

    void submit(Runnable task) throws InterruptedException {
        if (!taskQueue.offer(task, 500, TimeUnit.MILLISECONDS)) {
            throw new RejectedExecutionException("Queue full");
        }
    }

    void shutdown() { shutdown = true; }
}

HashMap uses an array of Node buckets. The index for a key is computed as (n-1) & hash(key), where n is the current capacity. Collisions are handled by chaining (linked list at each bucket). When a bucket's chain exceeds 8 elements and the total map size exceeds 64, the chain converts to a TreeMap (red-black tree) for O(log n) lookup within the bucket. The map resizes (doubles capacity) when the load factor threshold (default 0.75) is exceeded, rehashing all entries.

Reported from multiple Goldman Superday rounds as a "Java internals" probe. The follow-up is always: what's the time complexity for get() in the worst case? It's O(n) for a degenerate hash function with all keys mapping to the same bucket (before tree conversion), and O(log n) after the chain converts to a tree. O(1) is only the average case with a good hash distribution.

A subquery handles this cleanly: select the maximum salary from the rows where salary is less than the overall maximum. This works on the actual salary values rather than row position, so it stays correct even if the ordering of ties is ambiguous. A window-function alternative uses DENSE_RANK() over salary descending and filters for rank 2, which also handles ties gracefully and scales better if you need the Nth highest for an arbitrary N.

Reported across CoderPad screens for roles with a reporting or data component. The direct follow-up is always: what happens if two employees share the highest salary? The subquery version still returns the correct second-distinct value, while a naive OFFSET or LIMIT-based query can return a duplicate of the top salary instead, which is exactly the bug interviewers are checking whether you'll catch.

sql
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);

The trains meet in 1 hour (100 miles / (40 + 60 mph)). The bird flies for 1 hour at 200 mph, so it travels 200 miles. The elegant solution skips the infinite-series approach by noting the time to collision first. Goldman interviewers use this to see whether you reach for the elegant simple path or get trapped in unnecessary complexity. A candidate who starts summing a geometric series when the time-based answer is obvious is signaling something about their problem-solving instincts.

Two weighings. Divide into three groups: 3, 3, 2. Weigh the two groups of 3. If one side is heavier, the heavy ball is in that group. Weigh two of the three balls from that group against each other. If one is heavier, that's your ball. If they balance, the third is heavy. If the first weighing balances, the heavy ball is in the group of 2, which takes one more weighing.

This is a classic Goldman Sachs brain teaser reported across multiple candidate accounts. The trap is saying "three weighings" without working through the ternary logic. The minimum is two.

Set up states based on progress toward the goal: state S (no progress, or just flipped tails), state H (one head flipped so far). Let E be the expected flips from state S and E1 the expected flips from state H. From S, one flip either returns to S (tails, probability 1/2) or advances to H (heads, probability 1/2), so E = 1 + 0.5E + 0.5*E1. From H, one flip either finishes the sequence (heads, probability 1/2) or drops back to S (tails, probability 1/2), so E1 = 1 + 0.5E. Substituting gives E = 1.5 + 0.75E, so E = 6.

Expected-value coin puzzles like this show up in Goldman's earlier-stage and quant-flavored screens as a check on whether you can set up a system of equations from state transitions rather than reach for a memorized formula. Interviewers sometimes push the follow-up further: the same state-machine framing (no progress, partial match, done) is what a streaming pattern detector or a simple regex engine uses internally, and being able to draw that connection out loud is worth more than getting the arithmetic right.

Goldman's version of the "firefighting" story. The structure they're looking for: what was the system impact (not just "it was broken"), how did you diagnose it (specific tool, log, metric), what was your decision-making process under pressure, and what did you change after to prevent recurrence. "We added a monitor" is acceptable but weak. "We added a monitor on the specific metric that would have caught this 20 minutes earlier, and we added a runbook for on-call so the next engineer doesn't have to rediscover the diagnostic path" is better.

Quantify the impact. "Our service was down for 47 minutes affecting 3,000 users" is stronger than "the service was down." Goldman engineering teams deal with real financial consequences of downtime. Showing you think in terms of measurable impact signals cultural fit.

This is Goldman's integrity principle in practice. They want to see that you raise concerns with evidence and change your mind when new evidence arrives, not that you defer to authority by default. The strongest answers describe a specific technical disagreement, the data or reasoning you brought, the outcome of the conversation, and whether in retrospect the decision was correct. If the other person was right, say so.

Be careful not to frame this as "I was right and they were wrong." The best versions of this story acknowledge the legitimacy of the other perspective and describe a collaborative resolution. Goldman's culture is explicitly team-oriented. Heroic lone-dissenter stories don't land as well here as they might elsewhere.

Goldman's "broader contribution" question. Technology teams at the firm are large and cross-functional. Engineers who only work within their defined scope have less reach than those who improve shared infrastructure, tooling, or practices. The story should be specific: what was the friction you noticed, what did you build or change, how did it affect people beyond your team, and did you measure the impact?

Reported from multiple Goldman behavioral rounds. The interviewer almost always follows up with: "Did anyone resist the change? How did you handle it?" Have an honest answer, because most meaningful process improvements do face friction somewhere.

Goldman's integrity question in a technical frame. The expected answer arc: you raise the concern with specific reasoning (not just "I disagree"), you document it if it's material, you escalate if the concern involves compliance or risk and isn't being addressed, and you execute if the decision is made by someone with the authority to make it and doesn't cross a hard ethical line. Pure deference is a red flag. So is refusing to execute any decision you disagree with.

This question comes up more often in Goldman technology rounds than at most companies because Goldman engineers work on systems with real financial and regulatory stakes. Knowing where your personal line is and being able to articulate it clearly is part of what they're assessing.

Hard questions

7

Use DENSE_RANK() partitioned by client_id and ordered by trade_amount descending inside a common table expression, then filter the outer query for rank <= 3. You can't filter directly on a window function's result in the same SELECT's WHERE clause, because WHERE evaluates before window functions run, so the CTE (or a subquery) is required.

This is a finance-flavored variant of the classic "top N per group" SQL problem, and Goldman interviewers lean on it because it maps directly to real reporting needs on Controllers and Risk teams. The mistake almost every candidate makes on the first attempt is trying to reference the rank alias straight in a WHERE clause. Recognizing that error and reaching for a CTE without being told is what separates a pass from a near miss here.

sql
WITH ranked_trades AS (
  SELECT
    client_id,
    trade_id,
    trade_amount,
    DENSE_RANK() OVER (
      PARTITION BY client_id ORDER BY trade_amount DESC
    ) AS trade_rank
  FROM trades
)
SELECT client_id, trade_id, trade_amount
FROM ranked_trades
WHERE trade_rank <= 3;

Seven races. Split the 25 horses into five groups of five and race each group (5 races), which ranks the horses within their own group. Race the five group winners against each other (race 6). The winner of that race is the fastest horse overall, no further race needed for 1st place.

The harder part is finding 2nd and 3rd without over-racing. Eliminate any horse that provably can't be top 3: the 4th and 5th place group winners (and everyone in their groups) are out, since three faster horses already exist. From the remaining groups, only 5 horses can possibly be 2nd or 3rd: the 2nd and 3rd place finishers from the fastest group, the 2nd place finisher from the group whose winner placed 2nd overall, and the winner of the group whose winner placed 3rd overall. Race those 5 (race 7); the top two finishers give you 2nd and 3rd place overall.

First step is a thread dump, not guessing. jstack (or a heap dump snapshot from an APM tool if you can't SSH into the box) will literally print "Found one Java-level deadlock" along with the two thread stacks and which locks each one holds versus which lock it's blocked waiting on. That tells you the exact classes and methods involved in seconds, so you don't need to read through application logs first.

The classic cause is two code paths acquiring the same two locks in opposite order, thread A holds lock 1 and wants lock 2 while thread B holds lock 2 and wants lock 1. The fix is enforcing a global lock ordering (always acquire by, say, ascending object hash or a fixed sequence), or replacing nested synchronized blocks with java.util.concurrent.locks.ReentrantLock's tryLock(timeout) so a thread backs off and retries instead of blocking forever.

One thing worth distinguishing in an interview: not every "everything froze" incident is a true deadlock. Thread pool exhaustion looks identical from the outside, where a synchronized block makes a blocking network call and every worker thread ends up parked waiting on that call, starving the pool with no actual circular lock dependency. The thread dump disambiguates this immediately, since a real deadlock shows threads BLOCKED on each other's locks, while starvation shows threads WAITING on I/O or a latch. The long-term fix in both cases is the same discipline though, never hold a lock across a blocking call.

During a network partition you have to pick between consistency and availability, you can't have both, and for an order book the answer is almost always consistency. If a region gets cut off from the primary and you let it keep accepting orders locally, you risk two regions independently matching the same resting order against different incoming orders, which is a real trade discrepancy, not a cosmetic bug. So the standard design is a single authoritative region per instrument (or per book) that owns writes, with synchronous replication to a hot standby in the same or a nearby region for failover, and the remaining regions running as async read replicas that serve market data views but explicitly reject order placement during a partition.

For leader failover you want a consensus protocol like Raft rather than manual promotion, so a new leader is only elected once a quorum of nodes agrees, which bounds the window where two nodes could both believe they're primary (split brain). That gives you durability guarantees up to (N-1)/2 node failures in a 2f+1 cluster.

The nuance interviewers want you to catch is that you don't apply this same tradeoff uniformly across the whole system. The matching engine hot path stays single-writer and avoids distributed consensus entirely for latency reasons, most firms run it as one process pinned to a core with a write-ahead log for recovery. CAP tradeoffs get applied to the surrounding services instead, market data fan-out, position snapshots, risk aggregation, where eventual consistency across regions is an acceptable and even necessary tradeoff for availability.

Preorder traversal with explicit null markers is the cleanest approach, since it lets you rebuild the tree with a single pass and no extra bookkeeping. You write the root value, then recursively serialize the left subtree, then the right subtree, using a sentinel like "#" wherever a child is missing. Deserializing just replays the same order, consuming tokens one at a time, which works because preorder uniquely determines structure when nulls are marked.

Level-order (BFS) with a queue works too and some interviewers prefer it because it mirrors how you'd send the tree over a wire protocol level by level, but it needs a queue on both sides and is slightly more code to get right around missing children.

python
class Codec:
    def serialize(self, root):
        vals = []
        def dfs(node):
            if not node:
                vals.append('#')
                return
            vals.append(str(node.val))
            dfs(node.left)
            dfs(node.right)
        dfs(root)
        return ','.join(vals)

    def deserialize(self, data):
        vals = iter(data.split(','))
        def build():
            val = next(vals)
            if val == '#':
                return None
            node = TreeNode(int(val))
            node.left = build()
            node.right = build()
            return node
        return build()

Both serialize and deserialize are O(n) time and O(n) space for the output string and the recursion stack. The gotcha interviewers probe for is what happens with duplicate values or a tree that isn't a BST, and this approach handles both fine because it encodes structure directly through the null markers rather than inferring it from value ordering.

The goal is eliminating unpredictable stop-the-world pauses, since a 200ms full GC pause during a volatile market open can mean missed fills or stale risk numbers. G1GC is the safe default for most services, but for genuinely latency-sensitive paths you move to ZGC or Shenandoah, both designed for sub-millisecond pause targets even on multi-gigabyte heaps, because they do the heavy lifting (marking, compaction) concurrently with application threads instead of stopping the world.

Tuning the collector only gets you partway though, the bigger lever is reducing allocation pressure in the hot path itself. That means object pooling for anything created per-message (order objects, price ticks), using primitive arrays instead of boxed Integer/Double collections to avoid autoboxing garbage, and in the most latency-critical systems, moving hot data structures off-heap entirely using direct ByteBuffers so the collector never has to look at them. Some shops go further and write the matching engine core in a way that allocates zero objects per message once warmed up, so GC essentially never triggers during market hours.

A gotcha that's specific to trading systems: JIT warm-up matters as much as GC. If the JVM hasn't compiled hot methods to native code yet, the first few minutes after a cold start run in interpreted mode, which is its own latency cliff independent of garbage collection. Firms handle this by replaying synthetic traffic through the service before market open specifically to force the JIT to compile and inline the hot paths ahead of real traffic.

Read uncommitted allows dirty reads, read committed prevents dirty reads but still allows a row to change between two reads in the same transaction, repeatable read fixes that but still allows phantom rows to appear on range queries, and serializable prevents all of it by effectively running transactions as if they executed one at a time. The tradeoff going up that list is throughput, serializable is correct but forces more locking or retries under contention.

A lost update in a ledger typically looks like this: transaction A reads a balance of 100, transaction B reads the same balance of 100 concurrently, A computes 100 - 20 = 80 and writes it, then B computes 100 + 5 = 105 and writes it, overwriting A's withdrawal entirely. Under read committed with a naive read-then-write pattern, both transactions succeed and the database never complains, but the withdrawal silently disappears. You'd spot this in production by correlating the audit log timestamps, two writes to the same account within milliseconds where the second write's "before" balance doesn't match the first write's "after" balance is the signature.

The fix isn't just cranking the isolation level up, though SELECT ... FOR UPDATE to take a row lock before the read-modify-write, or serializable isolation with automatic retry on serialization failure, both work. The more robust fix for a ledger specifically is to avoid read-modify-write altogether: apply deltas as an atomic UPDATE balance = balance + :delta statement, which the database can execute as a single atomic operation without ever exposing an intermediate read to a race, and reserve full row locking for cases where you genuinely need to read a value and make a business decision based on it before writing back.

Real-time scenario questions

7

Combine a hash map with a doubly linked list. The hash map stores key to node references for O(1) lookup. The doubly linked list keeps nodes ordered by recency, most recently used at the head, least recently used at the tail. On get, move the accessed node to the head. On put, update and move to head if the key exists; otherwise insert at the head, and if capacity is exceeded, evict the tail node and remove it from the map.

One of the most consistently reported Superday questions across engineering levels at Goldman, occasionally appearing in the CoderPad screen for senior candidates instead. It's popular because it forces you to wire a hash map and a linked list together correctly under time pressure. A common follow-up asks how you'd make it thread-safe, which loops directly back to the concurrency primitives covered in the next section.

java
class LRUCache {
    class Node { int key, value; Node prev, next; }
    private final int capacity;
    private final Map<Integer, Node> map = new HashMap<>();
    private final Node head = new Node(), tail = new Node();

    LRUCache(int capacity) {
        this.capacity = capacity;
        head.next = tail;
        tail.prev = head;
    }

    private void remove(Node n) {
        n.prev.next = n.next;
        n.next.prev = n.prev;
    }

    private void insertAtHead(Node n) {
        n.next = head.next;
        n.prev = head;
        head.next.prev = n;
        head.next = n;
    }

    int get(int key) {
        if (!map.containsKey(key)) return -1;
        Node n = map.get(key);
        remove(n);
        insertAtHead(n);
        return n.value;
    }

    void put(int key, int value) {
        if (map.containsKey(key)) remove(map.get(key));
        Node n = new Node();
        n.key = key;
        n.value = value;
        map.put(key, n);
        insertAtHead(n);
        if (map.size() > capacity) {
            Node lru = tail.prev;
            remove(lru);
            map.remove(lru.key);
        }
    }
}

Core services: location tracking (driver heartbeats every 3 seconds via WebSocket or HTTP polling), matching engine (geospatial index, R-tree or geohash, to find nearby drivers), trip management (state machine: REQUESTED, DRIVER_ASSIGNED, IN_PROGRESS, COMPLETED), pricing service (surge pricing reads from demand/supply ratio in a geohash cell). For scale, the matching service is the hot path and must be in-memory with eventual consistency to a durable store.

Goldman's version of this question adds a compliance requirement: trip logs must be retained for seven years for regulatory purposes. That changes the storage tier design. You're not just building for query performance, you need a cold-storage archive path that regulators can query without affecting production latency.

Start with the core write path: UI sends a payment request to a Request Handler service, which validates and enriches the request (merchant lookup, fraud pre-check, idempotency key validation), then forwards to a Bank Integration service that handles partner-specific API contracts. Results write back to a cache and database. The fault-tolerance requirement is the hard part: when a banking partner is unavailable, you need a retry queue (Kafka works here) with exponential backoff and a dead-letter queue for manual investigation. Idempotency keys prevent duplicate charges on retry. The database write must be durable before any success acknowledgment to the user.

Reported directly from a September 2024 Goldman Sachs Superday (published on GeeksForGeeks). The interviewer pushed on what "real-time" means here: does the user see success after the DB write (synchronous confirmation) or after the bank actually settles (which can be T+1 or T+2 for ACH)? That distinction is Goldman-specific knowledge that most candidates from pure tech backgrounds miss.

Order book design is the center of this question. A price-time priority order book uses two sorted structures: a max-heap (or sorted map) of buy orders and a min-heap of sell orders. An incoming order matches if the best buy price is greater than or equal to the best sell price. Matching runs in O(log n) per order. For the latency requirement, in-process matching (no network hop for the book) is necessary at the microsecond scale. Event sourcing for the order book state provides the audit trail without blocking the matching path.

Follow-ups at Goldman include: how do you handle partial fills (update the remaining quantity, leave the order on the book), what happens when the matching engine crashes mid-match (event sourcing lets you replay from the last durable event), and how do you prevent wash trading (same entity on both sides). The wash trading question is regulatory compliance, not engineering, and Goldman interviewers expect you to flag it even if you don't have a complete solution.

Producer side: market data feeds arrive via FIX protocol or proprietary binary formats from exchanges. A normalized ingestion layer converts to a canonical schema. Kafka as the backbone provides ordered, durable, replayable streams. Consumer side: downstream services (pricing, risk, analytics) subscribe to relevant topics. For 1M events per second, partition Kafka by instrument symbol to allow parallel consumers without reordering issues within a symbol. At-least-once delivery with consumer-side deduplication handles the reliability requirement.

Schema drift is a real concern here: when an exchange changes its feed format, you can't take the pipeline down. A schema registry (Confluent Schema Registry or similar) with backward-compatible schema evolution handles this. Goldman interviewers specifically ask about this scenario because it's a problem they actually face.

Class hierarchy: Cart, Order, OrderItem, Payment, Refund. An Order transitions through states (PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED) using a state machine pattern. The Payment class handles status (INITIATED, AUTHORIZED, CAPTURED, FAILED, REFUNDED). Database schema: orders table with order_id, user_id, status, created_at; order_items with order_item_id, order_id, product_id, quantity, price_at_purchase (snapshot the price, never join to the live product table for historical orders); payments table with payment_id, order_id, status, gateway_txn_id.

Reported from a 2025 SDE2 Superday Round 6. The interviewer pushed hard on whether price_at_purchase should be denormalized (yes, because product prices change and you need the historical price for billing disputes). The SQL vs. NoSQL follow-up: orders and payments are relational, transactional, and have FK constraints, so SQL. Product catalog can be NoSQL for flexible attribute schemas, but the order line items snapshot the price at order time so catalog changes don't corrupt historical records.

The hard part isn't the algorithm, it's making the counter consistent across machines without killing latency. A local in-memory counter per gateway node is fast but wrong the moment you have more than one instance, since each node only sees its own slice of traffic. You need a shared store, and Redis is the usual choice because INCR and EXPIRE are atomic and it's fast enough to sit in the request path.

For the algorithm itself, fixed windows are simple but let traffic burst 2x at window boundaries. A sliding window log is accurate but expensive to store per-request timestamps at scale. The practical middle ground most firms use is a token bucket or the GCRA (generic cell rate algorithm, the one Stripe's rate limiter is built on), implemented as a Lua script in Redis so the read-check-decrement sequence is atomic and doesn't race across concurrent requests hitting different gateway nodes at the same instant.

The tradeoff you have to call out explicitly is the round trip to Redis on every request adds tail latency, and Redis itself becomes a single point of failure. Shard the limiter keys by user or API key across a Redis cluster to avoid one hot key, and decide up front whether the system fails open (allow traffic if Redis is unreachable, risking overload) or fails closed (reject everything, risking a full outage over a rate limiter blip). For most trading-adjacent APIs, failing closed on Redis unavailability is the safer default because unbounded traffic can cascade into the matching engine.

What we've seen across Goldman Sachs loops

Candidates who practice for Goldman Sachs loops through LastRoundAI show a consistent gap that prep guides don't address. The failure mode that ends most Goldman Superdays early isn't coding ability. It's showing up with a pure-tech mental model in an environment where financial constraints are first-class requirements.

The clearest signal: when asked to design a payment processing system, most candidates from pure-tech backgrounds jump to Redis and Kafka and skip the question of what "success" means from the client's perspective. A payment system at a bank has to be auditable, idempotent, and legally defensible. The candidate who says "every transaction needs a durable write before we send the user a success response, and the transaction ID needs to be globally unique and stored for seven years" is thinking like a Goldman engineer. The candidate who says "we'll use Redis for speed" without addressing durability is not.

The second pattern: Goldman behavioral rounds are more substantive than most candidates expect. The "Why Goldman over Google?" question ends more loops than any coding problem. Engineers who have thought seriously about what makes financial infrastructure interesting, and can articulate it in terms of specific engineering challenges, advance. Those who give generic prestige answers don't.

Leave a Reply

Your email address will not be published. Required fields are marked *