Stackadapt is an AdTech company. The Software Engineer role in this guide's sources spans programmatic bidding, infrastructure and UI-heavy feature development. On the backend it involves scalable microservices and data pipelines that make bidding decisions under tight latency limits and high throughput. On the front end it means feature development in React and JavaScript.
This guide's sources say candidates should show a solid grasp of their primary language, giving Go, Java or React/JavaScript as examples, and list proficiency in at least one high-performance language (Go, C++, Java or Scala) as a must-have. Listed nice-to-haves include AdTech or MarTech experience, real-time inference systems, GPU programming and financial trading systems. The responsibilities the sources describe also include code review and working with product teams to ship features.
Candidates report three stages over roughly three to five weeks: a recruiter screen, a series of technical interviews with live coding and system design, and managerial interviews on fit and behaviour. They also say the format varies by team. Be ready for rounds that combine coding and design, and prepare for both algorithmic coding and design in any technical round. Cover front-end fundamentals even if you are applying for backend work, because the reported questions include the CSS box model and React state management.
Recruiter Screen
reportedCandidates describe this as a recruiter conversation to review your background and check that you fit the role. They also report that later rounds vary by team and that some candidates did not know what to expect in specific rounds. Use this call to pin down the format of the next round: whether coding and design are separate or combined, which language and editor you will use, and whether the team covers front-end topics. Raise your hard constraints here as well, including start date, location, work authorisation and compensation range. It costs much less to resolve them before technical interviews are booked than at offer stage.
What to demonstrate
- How your background maps onto the areas this guide's sources describe for the role: programmatic bidding, infrastructure, or UI-heavy feature development
- Whether your constraints and expectations fit the role before technical rounds are scheduled
How to prepare
- Prepare a short account of your background, naming your primary language (the sources give Go, Java or React/JavaScript as examples) and the scale of the systems you have built
- Ask for the next round's format: coding, design or both, the editor you will code in, and whether front-end questions are in scope for the team
- Write your start date, location, authorisation and compensation range as one-line facts before the call so you can state them without negotiating live
Technical Interviews
reportedCandidates describe a series of technical interviews covering live coding and system design. Be ready for a session that combines coding and design, and for coding in a shared document or a basic editor without IDE support. Reported questions, which the sources do not tie to a specific round, fall into a few categories. Coding: detecting duplicates in an array, printing even numbers in a range, a graph problem, predicting a snippet's output (boolean logic, console.log, JavaScript closures) and sorting 1TB of data across machines with limited memory. Design: real-time bidding with millisecond latency, user-profile enrichment at scale, and the trade-off between throughput and latency. Technical knowledge: choosing a database, handling race conditions in distributed systems, the CSS box model, React state and testing a web application. Start with a working solution, then say how you would optimise it, and ask about input sizes before you commit to an approach.
What to demonstrate
- Whether you clarify constraints and input size before coding, and state time and space complexity for what you wrote
- Whether you can get a correct first version working in a plain editor and then improve it, instead of stalling while you look for the optimal answer
- Whether your design answers state a latency or throughput target and make trade-offs against it, including SQL versus NoSQL and consistency choices
- Whether you can trace code by hand to predict its output, including JavaScript scope and closure behaviour
How to prepare
- Code the reported shapes in a plain editor with no autocomplete: hash-set duplicate detection, BFS shortest path on a grid, and a range filter. State the complexity of each out loud
- Trace short JavaScript snippets by hand, such as var versus let in a loop that schedules setTimeout callbacks and truthy/falsy comparisons, then check your predictions in a real console
- Sketch a real-time bidding request path with a latency budget per hop and a no-bid response on timeout. Then do the same for profile enrichment with a batch path and a streaming path
- Rehearse the 1TB sort as an external sort: sample the keys to pick range boundaries, partition across machines, sort runs that fit in memory, and k-way merge
Managerial Interviews
reportedCandidates describe these interviews as assessing managerial fit and behaviour. Reported behavioural questions, which the sources do not tie to a specific round, include: a recent project you led from start to finish and its challenges, a disagreement with a teammate over technical architecture, how you prioritise competing deadlines under pressure, and what you want from your next role and why Stackadapt fits. Expect follow-ups that go past your summary into the architecture, the hurdles, your own contribution as distinct from the team's, and the business effect. Keep the facts of each story fixed, including team size, timeline and your role, so your account matches what you said in the technical interviews.
What to demonstrate
- Whether you separate your own decisions from the team's in a project you led
- Whether you settle a technical disagreement with evidence and commit to the outcome
- How you prioritise competing deadlines and explain what you deliberately dropped
- Whether your reasons for moving connect to the actual work described for the role
How to prepare
- Build one project deep dive with an architecture sketch, the hardest hurdle, your specific role and a measurable result
- Prepare an architecture disagreement story that names the failure mechanism you were worried about and what you did after the decision. The argue-and-lose behavioural drill in this guide follows that shape
- Write a two-sentence answer to 'why this role' that refers to the bidding, infrastructure or feature work described for it
- Write down three facts per story that must not change between tellings, and check each rehearsal against them
8 candidate reports. Individual accounts describe a particular role and hiring cycle.
Stackadapt Account Executive interview with shifting final rounds
My experience with the recruiter and recruiting manager was frustrating from the start because the logistics never felt stable. I was repeatedly told I'd be meeting one person, only for the meeting to change at the last minute. It became hard to keep track of who the actual hiring manager was, especially after I went through multiple rounds with people who all had the same title. I also received…
Read full experienceStackadapt Account Executive interview: three rounds with clear feedback
The interview process felt unusually smooth and respectful to me. The recruiter communicated throughout, and the company’s values came through in how people treated me. I wasn’t ghosted, and the process was clear. I went through three rounds and spoke with five different people. Those conversations helped me learn about the role and how the team worked. Each one felt honest and grounded rather th…
Read full experienceStackadapt Software Engineer three technical rounds
After a recruiter reached out and invited me to schedule, the process quickly became a sequence of conversations that felt somewhat shuffled compared with what I had been told. I completed an HR screen, then manager and culture-style interviews, followed by three technical rounds. Each technical round combined live coding with a system design prompt. What caught me off guard was that the intervie…
Read full experienceStackadapt Account Executive interview: 10-day project and presentation
The process felt more rigorous than I expected from the outside. After a recruiter screen, I interviewed with a Director about a week later. The conversation focused heavily on scenarios, and I also got deeper industry knowledge questions than I was ready for. The pacing and format changed as the rounds went on. Next was a project and presentation round with a Director and a Manager. I had 10 day…
Read full experienceStackadapt Software Engineer case study with unstable evaluation standards
My process started positively, but the final stage was deeply disappointing and left me uneasy about the evaluation standards. I was asked to complete what was presented as a case-study assignment for an enterprise agent solutions developer role. Although it was part of the interview, the work felt close to a real product and architecture project compressed into a short timeline. The most frustra…
Read full experiencePracHub editorial advice for the preparation topics above.
Guessing at a code-output question (console.log, boolean logic, closures) instead of tracing it
Reported questions include predicting the output of a snippet and explaining a JavaScript loop with closures. Trace the code line by line and write down each variable's value. Know the standard trap: for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)) prints 3, 3, 3, because var is function-scoped and all three callbacks share the same i. With let, each iteration gets its own binding and the output is 0, 1, 2. Also know that setTimeout callbacks run after the current synchronous code finishes, and that == coerces types while === does not.
Drawing boxes for the real-time bidding design without a latency budget or a timeout path
A design question about bidding with millisecond latency is really a question about the hot path. Start by stating the end-to-end budget as an assumption you will confirm, then split it across the hops. Keep the per-request work to in-memory or local lookups against precomputed data, such as enriched profiles and campaign state. Move logging, attribution and model updates off the request path into an asynchronous pipeline. Say what happens on a timeout: return a no-bid rather than a late bid. Then explain what you give up to hold latency, for example staleness in the precomputed data.
Answering the 1TB-across-a-fleet question as if the data fits on one machine
Ask how much memory each machine has and whether the output must be one globally sorted file or a set of sorted partitions. Then give the external-sort answer. Sample the keys to choose range boundaries, send each record to the machine that owns its range, and have each machine sort memory-sized runs and k-way merge them from disk. Because each partition holds a contiguous key range, concatenating the partitions in order gives a globally sorted result. Mention skew in the sample and how uneven partitions would be rebalanced.
Preparing only algorithms and backend design when candidates report front-end, testing and fundamentals questions
The reported technical and domain questions include the CSS box model, React state management, how you test a web application, choosing between database systems, and handling race conditions in a distributed system. The bank also covers web automation locators, CI/CD, and hash-map complexity. Prepare a short, concrete answer for each. For race conditions, name a mechanism such as an idempotency key, optimistic concurrency with a version column, or a conditional write. For database choice, tie the choice to the access pattern and consistency needs.
Giving a project story in a behavioural interview that cannot survive a follow-up
Reported behavioural questions ask about a project you led end to end and an architecture disagreement. Prepare one project so that you can sketch its architecture, name the hardest hurdle, say which decisions were yours, and give the business result. Keep team size, timeline and your role identical every time you tell it. If an earlier technical answer went badly, be ready to name what you missed instead of giving a polished second version.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Given a snippet of code, what is the expected output (e.g., boolean lo…
Given a snippet of code, what is the expected output (e.g., boolean logic or console.log behavior)?
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Walk one small example through your approach before writing the whole thing.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement a function to identify duplicate entries in an array or chec…
Implement a function to identify duplicate entries in an array or check for specific data patterns.
Approach
- State the target complexity and say which constraint rules the naive version out.
- Walk one small example through your approach before writing the whole thing.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Write a function to print even numbers within a specific range or solv…
Write a function to print even numbers within a specific range or solve a graph-based problem.
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- How does this change if the input no longer fits in memory?
- Which test case would catch an off-by-one here?
How would you sort 1TB of data using a fleet of PCs with limited memor…
How would you sort 1TB of data using a fleet of PCs with limited memory?
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Identify the heaviest tenants in a five-minute window under memory pressure
The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.
Approach
- Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
- Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
- State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
- Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.
- Choose and defend it: at 50,000 tenants the exact rings cost under 100 MB in a process that already holds more, so ship exact. Keep the sketch for the case that actually motivates it, a per-principal or per-IP key where cardinality runs to millions and is not bounded by anything you control.
- Raise the fleet problem before it is asked: each of 20 to 40 instances sees only its share, and the top 50 of one shard is not the top 50 of the fleet. Either aggregate counts centrally or accept that a per-instance threshold multiplied by instance count is the limit you are really enforcing.
Worked solution 25 min
- Size the exact structure: 300 one-second counters per tenant across 50,000 tenants, plus the running-total trick that makes a window read O(1).
- Write the top-k extraction with a size-50 min-heap and compare its complexity against sorting all 50,000 sums.
- Substitute N = 900,000 and m = 1,000 into N/(m+1) and state in requests what the sketch can and cannot distinguish.
- Write the sub-window merge for the sliding case and state the resulting bound for 30 merged summaries.
Follow-up
- The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
- Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?
- You switch to per-principal keys and cardinality goes to 10 million. Walk through what changes.
Replace offset paging on the resource feed with keyset
resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.
Approach
- Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
- Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
- Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
- Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.
- State the residual honestly. Keyset is stable against concurrent inserts and deletes, but not against a row whose updated_at changes mid-scroll — that row moves in the ordering and can be seen twice. If the feed must be a snapshot, order by an immutable key or bound the page set with updated_at <= the cursor's start value.
- Keep a total out of the page path. A tenant-wide COUNT(*) is the scan keyset just removed; fetch LIMIT 51 and return has_more instead.
Worked solution 25 min
- Seed one tenant with 500k active resources, 2% of them sharing an identical updated_at.
- Time LIMIT 50 OFFSET 0 against OFFSET 20000 and record rows-read from EXPLAIN (ANALYZE, BUFFERS) for each.
- Page the whole set with the keyset query while an insert-only writer adds 100 rows/second, collecting resource_ids, and repeat the run with OFFSET.
- Repeat both runs under a second writer profile that also deletes 20 rows/second from pages already returned and bumps updated_at on 20 more, and diff each collected id set against the rows that existed for the whole run.
- Remove resource_id from the cursor so the seek degrades to updated_at < $2, and re-run the tie-heavy section of the feed.
Follow-up
- The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
- Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?
- What does the cursor do when the row it points at has since been deleted?
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.
- Attach the tags for display after the page has been cut — LEFT JOIN LATERAL (SELECT array_agg(rt.tag_id) FROM resource_tag rt WHERE rt.resource_id = p.resource_id) ON TRUE over the 50 returned rows. Aggregate over the page, never over the tenant.
- Index both directions and say which query each serves: PK (resource_id, tag_id) serves the lateral lookup, (tag_id, resource_id) serves the EXISTS probe by tag, and resource_share needs (shared_with_user_id, resource_id) for the same reason. An index covering one direction only leaves the other as a scan.
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?
- Where does the correct total come from when the tenant holds 4M resources and the header must not cost 200 ms?
How would you architect a service to handle user-profile enrichment at…
How would you architect a service to handle user-profile enrichment at scale?
Approach
- State the consistency you need, and where you are willing to be stale.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the failure you are designing for, then the recovery path.
Follow-up
- What would you drop to keep the system up under load?
- What breaks first when traffic grows ten times?
Design a system to process real-time bidding requests with millisecond…
Design a system to process real-time bidding requests with millisecond latency.
Approach
- Choose a partition key and say what query it makes expensive.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Fix the scope first: who calls this, how often, and what they do when it fails.
Follow-up
- How does this behave when that dependency is down for an hour?
- What breaks first when traffic grows ten times?
How would you handle a race condition in a high-throughput distributed…
How would you handle a race condition in a high-throughput distributed system?
Approach
- Clarify what is being asked and what a complete answer contains.
- Work from the requirement backwards to the design.
- State your assumptions explicitly before working the problem.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Choose what to break when replication lag reaches forty seconds
Reads are served from two replicas: 14k requests/second, about 85% absorbed by cache, so roughly 2.1k reads/second reach the database. Writes go to the primary at 1.2k/second. A tenant's backfill drives replication lag from under 100 ms to 40 seconds and it is still climbing. Sessions that have just written are pinned to the primary. Decide, endpoint class by endpoint class, whether to serve stale, fail, or route to the primary, and justify each choice with the load it adds to the primary. Then state what you would have built beforehand.
Approach
- Establish blast radius before cause, because mitigation and diagnosis have different deadlines. The decisive arithmetic is what happens if the database reads move to the primary: 2.1k reads/second on top of 1.2k writes/second roughly triples its operation count, on the node already absorbing the backfill that caused this. Reads and writes are not equal in cost, so treat that as an argument against a blanket move rather than as a capacity model - but it is enough to rule out routing everything to the primary.
- Classify endpoints by what staleness costs, not by how important they feel. Reads whose staleness is invisible - listings, search, counters - stay on the replica and return the watermark so the client can tell. Reads that immediately follow that same session's write keep their primary pin, which is a small bounded slice of traffic rather than the whole 2.1k/second. Reads that feed a decision with a side effect - authorisation, quota, the read half of a read-modify-write - must not be stale at all, because a 40-second-old permission row is the stale-permission failure wearing a different costume; those go to the primary or fail.
- Shed instead of queueing. If the must-be-fresh class alone exceeds the primary's headroom, refuse its lowest-value slice with 503 and a retry-after. A request queued behind a saturated primary holds a connection for a client that has already given up, and the retry storm that follows is what turns degradation into an outage. Bound the connection pool per role so the read fallback cannot consume the write path's connections - that bulkhead is the single decision that determines whether writes survive the next ten minutes.
- Attack the cause in parallel, since it is the one thing that can be stopped. The backfill is the load generator. A backfill that reads replication lag as its throttle signal and pauses above a threshold would have made this a non-event, with batch sizes small enough that each batch's write volume is a fraction of what a replica can apply per second. That is most of the answer to what should have existed beforehand.
- Name the mechanism you would prefer over session pinning. Capture the write position at commit and require the read path to be at or past it: compare the primary's pg_current_wal_lsn() at commit time against the replica's pg_last_wal_replay_lsn(), and fall back to the primary only for the specific request that is ahead of the replica. Session pinning is the cheap approximation and it over-pins - every read in the window goes to the primary whether or not it needed to, which is a share of the cost being paid right now.
Worked solution 35 min
- List the endpoints in three buckets - staleness invisible, staleness visible to the writer only, staleness unsafe - and attach the share of the 2.1k reads/second each bucket carries.
- Compute the primary's operation count under each routing option and mark which options are arithmetically available.
- Write the pin rule and its window, then the shed rule: which slice, what status code, what retry-after.
- Write the backfill's throttle predicate against a measured lag value, including its pause threshold and resume condition.
Follow-up
- Lag returns to normal in nine minutes. Which mitigation do you remove first, and which one stays permanently?
- A user reports their change did not save, and the write committed. Trace the path that produces that report and name the signal that would have shown it before the report arrived.
- The replica is 40 seconds behind but otherwise healthy. Do you take it out of rotation? What does that do to the other replica's lag?
Every query on one table stalls for forty seconds mid-deploy
During a release on PostgreSQL, every query touching resource times out for about 40 seconds and then recovers with no intervention. The release ran one migration, ALTER TABLE resource ADD COLUMN archived_reason TEXT, and the migration log shows it completing in 6 ms. Unrelated tables showed no change in error rate. Explain how a 6 ms statement caused a 40-second stall, give the ordered checks you would run on a live system to confirm it, and give the migration procedure that prevents a repeat.
Approach
- Separate the statement's duration from the lock's duration. ADD COLUMN with no default is a catalogue-only change and genuinely runs in milliseconds, but it requires ACCESS EXCLUSIVE, and it cannot acquire that until every transaction already touching the table has finished.
- Account for the queueing, which is the part that surprises people. A lock request that is waiting blocks later requests for conflicting modes behind it rather than letting them overtake, so one long-open transaction holds the DDL and the DDL holds all the traffic. The stall length is set by the longest open transaction, not by the size of the change.
- Confirm on a live system in this order: pg_stat_activity for that table ordered by xact_start, looking for the oldest transaction and specifically for state = idle in transaction; then pg_locks where granted = false to find the waiter; then join them on pid to name blocker and blocked. pg_blocking_pids() does that join for you and is the fastest single call.
- Prevent rather than merely time it better. Set lock_timeout to a second or two on the migration session so the DDL abandons the queue after a bounded wait and is retried, instead of holding it for as long as the oldest transaction lives. Be exact about what that buys: queries arriving during the wait still queue behind the pending ACCESS EXCLUSIVE request, so each attempt costs them up to one lock_timeout of added latency. The outage goes from 40 seconds to about one second per attempt, not to zero. Also run migrations away from deploy-time peaks, and put a statement timeout and an idle-in-transaction timeout on the analytics role that opens the long transactions.
- Know the lock each change takes, since the mitigation differs by change. A column with a non-volatile default is a metadata-only change from PostgreSQL 11 and still needs the brief ACCESS EXCLUSIVE; an index needs CREATE INDEX CONCURRENTLY, which cannot run inside a transaction block and leaves an INVALID index to drop if it fails; a check or foreign key is added NOT VALID and then VALIDATE CONSTRAINT as a separate statement under a weaker lock.
Follow-up
- The same release also wants NOT NULL on that column. What is the sequence that gets there without a long lock?
- Your lock_timeout retry fails ten times in a row because the analytics transaction is always open. What do you change?
- How does this differ on MySQL with InnoDB online DDL, and what is the equivalent of the waiting-lock queue there?
Day one measures instead of guessing, under a fixed rubric, and the remaining hours are allocated in proportion to the gaps before any studying begins. The allocation is deliberately not renegotiated midweek, because the area that feels worst on day three is usually the one that is moving.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Recruiter screen and format questions
- Write a short background summary that names your primary language (for example Go, Java or React/JavaScript) and the largest system you have worked on
- List your hard constraints (start date, location, authorisation, compensation range) as one-line facts
- Write the questions you will ask about the technical rounds: coding, design or both, which editor, and whether front-end topics are in scope
Deliverable: A one-page screen sheet with your background summary, constraints and format questions.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Core coding in a plain editor
- In an editor with no autocomplete, solve the reported shapes: duplicate detection with a hash set, a range filter such as even numbers in [a, b], and BFS shortest path on an obstacle grid
- For each one, state the time and space complexity out loud before running it, then write the edge cases: empty input, a single element, an unreachable target
- Review hash-map behaviour for the bank questions on dictionary operation complexity and Java HashMap collisions: average O(1), and the worst case when many keys collide
Deliverable: Three working solutions, each with its complexity and edge cases written above the code.
Practice prompt ↗Practice prompt ↗03Code-output, JavaScript and front-end fundamentals
- Trace a set of short snippets by hand before running them, covering var versus let in loops with setTimeout, closures, == versus ===, and truthy/falsy values
- Write short answers to the reported front-end questions: the CSS box model (content, padding, border, margin, and what box-sizing changes) and how React components hold and update state
- Write out how you would test a web application and inspect a page, including how to choose stable element locators
Deliverable: A sheet of traced snippets with predicted and actual output, plus written front-end answers.
Practice prompt ↗Practice prompt ↗04Large data, concurrency and counting
- Talk through sorting 1TB across machines with limited memory: sample the keys for range boundaries, partition, sort memory-sized runs locally, k-way merge
- Answer the race-condition question with specific mechanisms: an idempotency key, a version column with a conditional update, or a single-writer partition
- Work through the heavy-tenants worked exercise (drill-coding-3) and check your exact ring-buffer and Misra-Gries bounds against it
- Sketch the bank's time-windowed key-value store and state the complexity of get and put
Deliverable: Written answers to the 1TB sort and race-condition questions, plus a completed heavy-hitter exercise.
Practice prompt ↗Practice prompt ↗Worked solution ↗05System design: bidding, enrichment and throughput versus latency
- Design the reported real-time bidding system with an explicit latency budget per hop, precomputed lookups on the hot path, and a no-bid response on timeout
- Design user-profile enrichment at scale with a streaming update path and a batch backfill, and say where the profile store may be stale
- Work through the replication-lag worked exercise (drill-design-4) and practise stating each routing decision as a load on the primary
- Write one paragraph on when you would give up throughput for latency and when you would do the reverse
Deliverable: Two design sketches, each with a latency or throughput target and one named trade-off.
Practice prompt ↗Practice prompt ↗06Databases, SQL and debugging
- Write a comparison of relational and NoSQL stores keyed to access pattern and consistency needs, for the reported database-choice question
- Do the keyset pagination worked exercise (drill-sql-1) and the bank topics on INSERT and UNION
- Work the lock-stall debugging drill (drill-debugging-5), and for each check state what result would confirm or rule out the hypothesis
Deliverable: A database-choice comparison, a verified keyset query, and an ordered debugging checklist.
Practice prompt ↗Practice prompt ↗07Managerial interviews and a combined mock
- Rehearse the reported behavioural questions aloud: a project you led end to end, an architecture disagreement, prioritising competing deadlines, and why Stackadapt
- Build the argue-and-lose story from drill-behavioral-6, naming the predicted mechanism and what you instrumented afterwards
- Run a mock round that combines a coding question and a design follow-up in one session, since a technical round may combine both
- Write three facts per story that must stay fixed across tellings
Deliverable: Four rehearsed behavioural answers with fixed facts, and notes from one combined coding-and-design mock.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The reported behavioural questions focus on ownership, technical disagreement, prioritisation and motivation. For each one, prepare a story where you made the decision, can sketch the architecture involved, and can give a concrete result. Keep team size, timeline and your role consistent across rounds, and end each story with what you would do differently.
Describe a recent project you led from start to finish. What were the …
Describe a recent project you led from start to finish. What were the challenges?
Approach
- Close with what you would do differently, concretely.
- Pick a story where you made the decision, not one where you watched it.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- How did you know your change caused the improvement?
- What would you do differently if you ran that again?
Tell me about a time you had to handle a disagreement with a team memb…
Tell me about a time you had to handle a disagreement with a team member regarding technical architecture.
Approach
- Pick a story where you made the decision, not one where you watched it.
- Close with what you would do differently, concretely.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What did you decide not to do, and why?
- How did you know your change caused the improvement?
Argue against a design, lose, and commit anyway
Describe a design you argued against and lost. State the failure you predicted as a named mechanism, not a feeling about complexity: two services that would need one transaction, a projection with no rebuild path, a write path with no idempotency key. Say what evidence you brought, what the decision maker weighed instead, and what you did after the decision was made: what you instrumented, what you wrote down, and whether the prediction came true. Five minutes.
Approach
- State the prediction in falsifiable form up front: the mechanism, the condition that triggers it, and the observable outcome. A prediction that cannot be checked also cannot be credited to you later.
- Show the evidence you had at the time and label each piece honestly as measured, analogous, or intuition. Keeping the intuition is fine; disguising it as data is the thing that erodes your standing in the next argument.
- Represent the opposing case at full strength, including the constraint you did not control: a fixed date, a team boundary, or the fact that the decision was cheap to reverse and yours was not.
- Make disagree-and-commit concrete. Name the artefact you left behind so the prediction could be settled without you: the alert and its threshold, the counter on the dashboard, the decision note that recorded the trade-off and the condition that would revisit it.
- Report the outcome without editing it. If the design held and your predicted mechanism never fired, say so and say what you had mis-weighted, which is more persuasive than a vindication story.
Follow-up
- What threshold on that alert would have proved you right, and did anyone ever look at it?
- If the same proposal arrived tomorrow with the same deadline, would you argue it the same way?
- How did you behave toward the design once it shipped and started failing in a different way than you predicted?
- 01
Describe a recent project you led from start to finish. What were the challenges?
- 02
Tell me about a time you had to handle a disagreement with a team member regarding technical architecture.
- 03
How do you prioritize tasks when faced with competing deadlines and high-pressure requirements?
- 04
What are you looking for in your next role, and why does Stackadapt align with your growth?
- 05
Describe a design you argued against and lost: the failure mechanism you predicted, the evidence you brought, and what you instrumented or wrote down after the decision.
Is this an official Stackadapt interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Stackadapt. Rounds and questions reflect what candidates have reported, not a process Stackadapt has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult are the technical interviews?
Candidates describe them as average to difficult, with algorithmic coding and system design both in play. The reported coding questions range from easy (duplicates in an array) to open-ended (sorting 1TB across machines). If you do not see the optimal solution straight away, get a correct version working, explain your reasoning, and then say how you would optimise it.
PracHub interview research ↗Is the interview process organized?
Experiences vary. Some candidates describe the process as professional and fast, while others say they were unclear about what specific rounds would involve, and the format reportedly varies by team. Ask the recruiter for a clear breakdown of each round's format. Even so, prepare for both coding and design in any technical round.
PracHub interview research ↗Which languages should I be ready to code in?
This guide's sources ask candidates to show a solid grasp of their primary language, giving Go, Java or React/JavaScript as examples, and list proficiency in at least one high-performance language (Go, C++, Java or Scala) as a must-have. Use the language you know best, and make sure you can write idiomatic code in it from memory, because you may be coding in a shared document or basic editor without IDE support.
PracHub Software Engineer practice ↗Do I need front-end knowledge if I am applying for backend work?
Prepare for it. The reported technical questions include the CSS box model, React state management, testing a web application, and predicting JavaScript output, including closure behaviour inside loops. Prepare a short, accurate answer to each so that none of them catches you unprepared.
PracHub Software Engineer practice ↗How should I split my preparation time?
Split it across the categories candidates report: core coding and complexity, code-output and JavaScript fundamentals, large-data and concurrency questions, system design centred on latency and throughput, databases, and behavioural stories. The 7-day plan in this guide covers each of these once, and it includes worked exercises on pagination, heavy-hitter counting and replication lag.
PracHub interview research ↗What is the working environment like?
Candidates describe it as fast-paced and performance-driven. Accounts differ, so use the managerial interviews to ask about how the team works day to day: how priorities are set, how code review runs, and how on-call is shared. Decide based on those answers rather than on general reputation.
PracHub interview research ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-24 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-24 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-24