Interview guides · Affinity
Affinity Software Engineer Interview Guide
Affinity Software Engineer interview guide: the three reported rounds, web, MySQL, design, coding and behavioral questions, and a 7-day prep plan.
The 60-second brief
Candidates describe Affinity as a company with user-facing products, and describe the Software Engineer role as building and maintaining scalable software behind them. The reported day-to-day work is building features alongside product managers, designers and other engineers, fixing defects, taking part in code reviews and refactoring existing code. The reports name no specific product, customer or team, so this guide does not guess at them. Read the posting you applied to for team details.
This guide is for candidates interviewing for a Software Engineer role at Affinity. It covers the three reported stages and the question families candidates report: technical and domain questions, system design, problem-solving cases, coding and behavioral. The stack candidates describe includes JavaScript, HTML5, CSS, MySQL and SQL, with Python or Ruby as alternative languages. React, Vue.js, AWS and Azure are described as nice to have.
Candidates report three stages: a half-hour informational call with the engineering director, technical interviews with engineers, and behavioral interviews. Reported timelines run from roughly 3-5 weeks to 4-6 weeks.
Focus areas
- System Design (Service Implementation)
- JavaScript
- Web Technologies
Overview
The reported topic list for this role is a web-development stack: JavaScript, HTML5, CSS, browser behaviour, MySQL and service implementation. The requirements candidates describe add RESTful API design and SQL, with React, Vue.js and a cloud provider as extras. Preparing for this loop therefore means being able to explain how a web application works from browser to database. Example questions candidates report include how to implement a feature with modern web technologies, how to optimize a slow API response, and the difference between XAMP and WAMP environments.
The reported questions fall into five families. Technical and domain questions cover web protocols, state management in a web application, RESTful API design and your relational database experience. Design questions cover real-time data processing, microservices, fault tolerance, scalability and trade-offs from your own architectural decisions. Problem-solving cases cover building a feature from requirements, debugging production, slow applications, analytics-driven engagement and a mid-project pivot. Coding questions are longest substring without repeating characters, binary search, trees or graphs, sorting a large dataset and reversing a linked list. Candidates describe coding as something you may be asked to do, not a certainty, so be ready for it.
The technical stage is reported to centre on your past projects and how you solve problems, so your own work is the main study material. Pick two projects you can describe in depth: the architecture, the part you owned, one bug, one trade-off and one measured result. Those same projects supply most of your answers in the behavioral stage, where candidates report questions on collaboration, prioritising, advocating for a technical decision and handling conflict. Keep a story bank so one project does not carry every answer.
The Affinity interview process
Candidates describe three stages, in the order below. Reports give no format details beyond each stage's purpose, so confirm logistics with your recruiter.
Initial Screening
Candidates report a half-hour informational call with the engineering director. It is described as a chance to learn about the company and to share your background, and no coding or design exercise is reported for it. Treat it as a two-way conversation: a short career narrative from you, then specific questions about the engineering team.
What to demonstrate
- How you describe your background: roles, projects and the languages you work in
- Your reasons for applying and the questions you ask about the engineering team
How to prepare
- Write a short career narrative that names the languages and tools you have shipped with, mapped to JavaScript, Python or Ruby, and SQL.
- Choose the one project you would be happiest to discuss in depth in the technical interviews, and be ready to say what you owned in it.
- Write three questions for the director about how features move from product managers and designers to release, and how code review works on the team.
- Ask what the remaining stages look like and who you will meet, then note the answer.
Technical Interviews
Candidates report multiple technical interviews with engineers of varying experience levels, centred on your past projects and how you approach problems. The coding, design, problem-solving and technical and domain questions in this guide are the material this stage draws on. Topics candidates list for the role are JavaScript, HTML5, web technologies, MySQL and service implementation. Approach it by narrating: restate the problem, state assumptions, give a first solution with its cost, then improve it.
What to demonstrate
- Depth on your past projects: what you built, decided and measured
- Problem-solving approach, including how you break problems into parts and choose data structures and algorithms
- Working knowledge of web technologies and MySQL, including writing efficient queries
How to prepare
- For two projects, write a sheet with the architecture, your own contribution, one bug you diagnosed and one trade-off you made.
- Refresh JavaScript fundamentals you may be asked about: closures, the event loop, promises and async/await, and how the browser handles events.
- Write queries by hand for joins, GROUP BY and HAVING, and practise reading EXPLAIN output on MySQL for a slow query.
- Solve the longest substring, binary search and linked-list reversal questions aloud in JavaScript or Python, stating complexity and edge cases each time.
Behavioral Interviews
Candidates report behavioral interviews aimed at interpersonal skills and cultural fit. The leadership themes reported are facilitating discussion and building consensus, mentoring junior engineers, and handling conflict or differing opinions. Approach it with a bank of real stories, each with your decision, your reasoning and a result, rather than general statements about how you work.
What to demonstrate
- Collaboration with a team and with cross-functional partners
- Leading or influencing a technical decision, and handling disagreement
- How you prioritise across several projects
How to prepare
- Write five stories from real work: a hard project, a prioritisation call, a team collaboration, a technical decision you argued for and a conflict.
- For each story, note the decision you personally made, the alternatives, and an outcome you can state with a number or a concrete change.
- Add a mentoring example with a junior engineer, since mentorship is a reported leadership theme.
- Rehearse each story aloud in about a paragraph and check that you say what you did, not only what the team did.
Where candidates lose points
Answering the web-state question by naming a library instead of explaining where state lives
Separate server data, client UI state, URL state and persisted state, say where each should live, and name the trade-off of each. Then place a library such as React or Vue.js in that picture if you have used one.
Listing database features when asked about your relational database experience and the queries you wrote
Bring three real queries: a join, an aggregation and one tuned with an index after EXPLAIN. Be ready to explain every clause, since MySQL and SQL are in the reported requirements.
Drawing boxes for the microservices, fault-tolerance or real-time processing design questions without requirements or failure modes
Open with scale, latency and consistency requirements, then name what happens when each dependency fails, using retries with backoff, timeouts, idempotency and queues where they fit.
Coding the longest substring, binary search or linked-list question silently, with no complexity analysis or edge cases
Narrate: restate the input, give the brute-force cost, then the improved approach. Test on an empty input, a single element and repeated characters, and state time and space complexity.
Being unable to go deep on your own projects when the technical stage centres on them
Prepare two project sheets covering architecture, your contribution, a bug and a trade-off. Rehearse follow-ups on why you chose each technology.
Questions & practice
Write a function to find the longest substring without repeating characters.
Medium · Coding / Algorithms
Approach
- Brute force checks every substring for duplicates in O(n^3), or O(n^2) with a set per start index; say that before optimising.
- Use a sliding window with a map from character to its last index: for each right index, if the character was last seen at or after left, move left to that index + 1; update the best length as right - left + 1.
- Moving left with max(left, last[c] + 1) prevents the window from moving backwards when the stored index is stale; each character is processed once, so time is O(n) and space is O(min(n, alphabet size)).
- Edge cases: empty string returns 0, all identical characters return 1, all distinct return n; in JavaScript, indexing a string reads UTF-16 code units, so emoji count as two unless you iterate with for...of or Array.from.
Follow-up
- Return the substring itself, not just its length.
- How would you find the longest substring with at most k distinct characters?
- How does the solution change for a stream too large to hold in memory?
How would you implement a binary search algorithm?
Medium · Coding / Algorithms
Approach
- State the precondition: the array is sorted (or the predicate is monotone); binary search halves the search space each step, giving O(log n) time and O(1) space iteratively.
- Fix one invariant and keep it: with an inclusive range use lo = 0, hi = n - 1, loop while lo <= hi, and move lo = mid + 1 or hi = mid - 1; with a half-open range [lo, hi) loop while lo < hi and set hi = mid.
- Compute mid as lo + (hi - lo) / 2 (integer division) to avoid overflow in fixed-width integer languages; Python integers do not overflow, and JavaScript numbers are exact up to 2^53.
- With duplicates, write the lower-bound variant (first index with a[i] >= target) and derive first and last occurrence from it; test empty arrays, one element, the target absent, below the minimum and above the maximum.
Follow-up
- Search for a target in a sorted array that has been rotated.
- Find the smallest value x for which a monotone condition holds (binary search on the answer).
- How would you search a sorted list whose length you do not know?
Solve a problem that involves manipulating data structures like trees or graphs.
Medium · Coding / Algorithms
Approach
- Pick the representation first: an adjacency list costs O(V + E) space and suits sparse graphs; an adjacency matrix gives O(1) edge checks at O(V^2) space.
- Choose the traversal from the question: BFS for shortest paths in unweighted graphs and level order in trees, DFS for connectivity, cycle detection and path enumeration; both run in O(V + E) with a visited set on graphs.
- Name the specialised algorithm when it applies: topological sort (Kahn's algorithm with in-degrees) for dependencies, Dijkstra with a binary heap in O((V + E) log V) for non-negative weights, union-find for connected components under edge additions.
- For trees, use recursion that returns a value per subtree (height, sum, validity bounds for a BST); a skewed tree makes recursion depth n, so switch to an explicit stack when Python's default recursion limit of 1000 could be hit.
- Edge cases: empty tree or graph, disconnected components, self-loops, cycles in what was assumed to be a tree, duplicate edges.
Follow-up
- How do you detect a cycle in a directed graph, and how does that differ from an undirected one?
- Given course prerequisites, return a valid order or report that none exists.
- How would you find the lowest common ancestor of two nodes in a binary tree?
Discuss your approach to sorting a large dataset.
Medium · Coding / Algorithms
Approach
- Ask how large, what key type, and whether stability matters; if it fits in memory, use the language sort: Python's sorted is Timsort (stable, O(n log n), fast on partly sorted data), and JavaScript's Array.prototype.sort is stable since ES2019 but compares as strings by default, so numbers need (a, b) => a - b.
- Know the trade-offs: quicksort is O(n log n) on average but O(n^2) with bad pivots, heapsort is O(n log n) worst case with O(1) extra space but not stable, merge sort is stable with O(n) extra space.
- For bounded integer keys, counting or radix sort beats comparison sorting at O(n + k) or O(d(n + b)).
- When the data exceeds memory, use an external merge sort: sort chunks that fit in RAM, write sorted runs to disk, then k-way merge them with a min-heap of size k, so the cost is dominated by sequential I/O passes.
- Often you do not need a full sort: top k needs a size-k heap in O(n log k), and in MySQL an index that matches ORDER BY avoids a filesort; across machines, sample keys to range-partition data, sort each partition and concatenate.
Follow-up
- How many merge passes does an external sort need for a given memory size and file size?
- How would you find the 100 largest values in a billion-row file?
- Why does stability matter when sorting by several keys?
Write code to reverse a linked list and explain your thought process.
Medium · Coding / Algorithms
Approach
- Iterate with three pointers: prev = null, curr = head; on each step save next = curr.next, set curr.next = prev, then move prev = curr and curr = next; return prev as the new head.
- State the cost: O(n) time and O(1) extra space; a recursive version is also O(n) time but uses O(n) call stack, which can overflow on long lists.
- Trace it out loud on a three-node list to show no node is lost, since saving next before relinking is the step that prevents losing the rest of the list.
- Edge cases: empty list, single node, two nodes, and making sure the old head's next ends up null so the result has no cycle.
Follow-up
- Reverse only the nodes between positions m and n.
- Reverse the list in groups of k nodes.
- Use reversal to check whether a linked list is a palindrome in O(1) extra space.
Find version gaps and relay lag with window functions
Medium · window functions · event tables · frame semantics
outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.
Approach
- Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
- Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
- Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
- Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.
Follow-up
- Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
- Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?
Hold a per-tenant active cap against concurrent creates
Hard · write skew · isolation levels · constraints
A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.
Approach
- Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
- Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
- Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
- State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.
Follow-up
- A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
- The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?
Explain how you would implement a hypothetical service.
Medium · Technical / Domain Questions
Approach
- Pin the service down before designing it: name one concrete example (say, a notification or URL-shortening service), its callers, the read/write ratio, the latency target and what a caller does when it fails.
- Write the REST contract first: resources, methods, request and response bodies, status codes, and an idempotency key on any POST a client may retry.
- Model the data in SQL: tables, primary keys, the secondary indexes each query needs, and which writes must share a transaction.
- Keep the app tier stateless behind a load balancer so it scales horizontally; push slow side effects (email, webhooks) onto a queue with workers, and add a cache only for a measured hot read path.
- Close with operability: structured logs, metrics on p95/p99 latency and error rate, health checks, and how a schema change ships without downtime (expand, backfill, then contract).
Follow-up
- How do you stop a retried request from creating a duplicate record?
- Which part of this design fails first at ten times the traffic, and what do you change?
- How would you add a column to a large, busy table without locking writes?
What are the differences between various web protocols?
Medium · Technical / Domain Questions
Approach
- Lay out the stack: HTTP rides on TCP (HTTP/1.1 and HTTP/2) or on QUIC over UDP (HTTP/3); HTTPS is HTTP over TLS, which adds encryption, integrity and server authentication.
- HTTP/1.1: text headers, persistent keep-alive connections, one outstanding response per connection in practice, so browsers open several connections per origin.
- HTTP/2: binary framing, many multiplexed streams on one TCP connection and HPACK header compression; a single lost TCP packet still stalls every stream (transport-level head-of-line blocking).
- HTTP/3: QUIC gives each stream independent loss recovery, builds TLS 1.3 into the handshake for fewer round trips, and lets a connection survive a client IP change.
- For push-style traffic, compare WebSockets (an HTTP Upgrade to a full-duplex channel), Server-Sent Events (one-way server-to-client text stream over plain HTTP with built-in reconnect) and long polling, and say when each fits.
Follow-up
- Walk through what happens between typing a URL and the first byte of HTML arriving.
- For a live dashboard, would you pick WebSockets or Server-Sent Events, and why?
- Why can HTTP/2 perform worse than HTTP/1.1 on a lossy mobile network?
How do you manage state in a web application?
Medium · Technical / Domain Questions
Approach
- Sort state by where it lives: local component UI state, shared client state, server state (data fetched from an API), URL state (route and query params), form state and persisted state (cookies, localStorage).
- Keep one source of truth per piece of data and compute derived values instead of storing them; copying server data into a global store invites stale, inconsistent copies.
- Treat server state as a cache: a fetching layer such as React Query or SWR handles caching, deduplication, refetching and invalidation after mutations; reserve Redux, Pinia or Context for state that really is global on the client.
- HTTP is stateless, so explain session handling: a session id cookie backed by a server-side store versus a signed token such as a JWT; set HttpOnly, Secure and SameSite on auth cookies, and know that a JWT cannot be revoked before expiry without a denylist or short lifetimes.
- Name the edge cases: optimistic updates that must roll back on error, race conditions when responses arrive out of order, and keeping several tabs in sync (the storage event or BroadcastChannel).
Follow-up
- How would you implement an optimistic update and roll it back if the server rejects it?
- When would you put state in the URL rather than in a store?
- How do you log a user out everywhere if sessions are JWTs?
Discuss the importance of RESTful APIs and their design principles.
Medium · Technical / Domain Questions
Approach
- Model resources as nouns with stable URLs (/users/{id}/orders) and let HTTP methods carry the verb; GET is safe and idempotent, PUT and DELETE are idempotent, POST is not, and PATCH is not guaranteed to be.
- Use status codes precisely: 201 with a Location header on create, 204 for an empty success, 400 versus 422 for bad input, 401 (not authenticated) versus 403 (not allowed), 404, 409 for conflicts, 429 for rate limits.
- Keep requests stateless so any server can handle any call, and use caching headers (Cache-Control, ETag with If-None-Match returning 304) to cut repeat reads.
- Paginate large collections with a cursor (WHERE id > :last ORDER BY id LIMIT n) rather than a large OFFSET, which makes the database read and discard every skipped row.
- Plan for change: version the API (path or header), only add optional fields within a version, give POSTs an idempotency key, and return 202 Accepted plus a status resource for long-running work.
Follow-up
- When would you choose GraphQL or gRPC over REST?
- How would you ship a breaking change to an API that external clients depend on?
- How would you design a bulk-update endpoint where some items fail?
Design a system that can handle real-time data processing.
Medium · System Design / Architecture
Approach
- Clarify the numbers that shape the design: events per second, end-to-end latency target, whether per-key ordering matters, and whether duplicates or loss are acceptable.
- Ingest into a partitioned, replayable log (Kafka or Kinesis, for example), keyed so all events for one entity land in one partition and keep their order; watch for hot keys.
- Process with a stream processor (Flink, Kafka Streams, Spark Structured Streaming): define windows (tumbling, sliding, session), use event time with watermarks for late data, and checkpoint operator state so a restart resumes correctly.
- State the delivery semantics: at-least-once delivery plus an idempotent sink (upsert keyed by event id) gives effectively-once results without distributed transactions.
- Serve results from a fast store (Redis for counters, an OLAP store for queries) and push updates to clients over WebSockets or Server-Sent Events; monitor consumer lag and apply backpressure when processors fall behind.
Follow-up
- How do you handle events that arrive after their window has closed?
- What happens if one key produces most of the traffic?
- How would you reprocess a day of data after fixing a bug in the processing logic?
How would you approach designing a microservices architecture?
Medium · System Design / Architecture
Approach
- Start by justifying the split: independent deployability and scaling per domain, paid for with network failures, versioning and operational overhead; for a small team, a modular monolith with clear boundaries is often the better first step.
- Draw service boundaries around business capabilities, and give each service its own data store; a shared database couples services back together.
- Choose communication per interaction: synchronous REST or gRPC when the caller needs an answer now, asynchronous events through a broker when it does not, which also decouples availability.
- Replace cross-service transactions with sagas (local transactions plus compensating actions) and publish events reliably with the transactional outbox pattern.
- Name the platform pieces: API gateway, service discovery, per-service CI/CD, centralised logs, distributed tracing with a correlation id, and contract tests between consumers and providers.
Follow-up
- How would you split an existing monolith without a rewrite?
- A page needs data owned by three services; how do you serve it efficiently?
- How do you keep an event schema backward compatible as it evolves?
Describe how you would ensure fault tolerance in a distributed system.
Medium · System Design / Architecture
Approach
- Remove single points of failure: several stateless instances across availability zones behind a health-checked load balancer, and replicated data stores with automated failover.
- Put a timeout on every network call, retry only idempotent operations (or those carrying an idempotency key), and use exponential backoff with jitter so retries do not synchronise into a storm.
- Contain failure: circuit breakers stop calls to a dependency that keeps failing, bulkheads give each dependency its own pool, and load shedding rejects excess work early.
- For data, explain replication trade-offs: asynchronous replicas can lose recent writes on failover, while quorum systems with W + R > N guarantee a read overlaps the latest acknowledged write.
- Degrade gracefully (serve cached or partial results), send poison messages to a dead-letter queue, and prove the design with failure-injection tests against defined SLOs.
Follow-up
- How do you prevent split brain when the primary database becomes unreachable?
- A downstream service slows rather than fails; what protects your service?
- How do you give a user read-your-writes consistency with lagging replicas?
What factors do you consider when designing for scalability?
Medium · System Design / Architecture
Approach
- Start from load: requests per second at peak versus average, the read/write ratio, data growth per month and the latency target at p95/p99, since averages hide the slow tail.
- Scale the app tier horizontally by keeping it stateless (sessions in a shared store or signed tokens) behind a load balancer.
- Cut read load with caches at each layer (CDN for static assets, cache-aside in Redis with TTLs and explicit invalidation) and watch for stampedes when a hot key expires.
- Scale the database in order of cost: indexes and query fixes, connection pooling, read replicas (accepting replication lag), then partitioning or sharding on a key that spreads writes evenly and keeps common queries on one shard.
- Move slow work to queues and workers, and say what gets expensive: cross-shard queries, rebalancing, and operational cost.
Follow-up
- What breaks first when traffic grows tenfold, and how would you know before users do?
- How do you pick a shard key, and what happens if you pick badly?
- How do you stop thousands of requests rebuilding the same expired cache entry?
Discuss trade-offs you’ve encountered in past architectural decisions.
Medium · System Design / Architecture
Approach
- Choose one real decision with at least two viable options, and state the constraint that made it hard (load, deadline, team skills, consistency requirement).
- Name the axes explicitly: for example consistency versus latency, SQL versus a document store, synchronous calls versus a queue, building versus buying, monolith versus services.
- Show the evidence behind the choice: a benchmark, load numbers, a prototype or a cost estimate, and say how reversible the decision was.
- Report what it cost later in measurable terms, in the first person: what I gave up, where it hurt, and what I would decide differently with today's information.
Follow-up
- What signal would have made you reverse that decision?
- Which option you rejected looks better now, and why?
- How did you get the rest of the team to accept the trade-off?
Given a set of user requirements, how would you approach building a new feature?
Medium · Problem-Solving / Case Studies
Approach
- Turn the requirements into acceptance criteria: who the user is, the main flow, edge states (empty, error, permission denied) and non-functional needs such as performance and accessibility; list open questions for the product owner.
- Design the change end to end: data model and migration, API contract, UI components and state, and where validation lives (always on the server, mirrored on the client for feedback).
- Slice the work into small shippable increments behind a feature flag, with backward-compatible migrations (add the column, backfill, switch reads, then remove the old path).
- Test at the right levels: unit tests for logic, integration tests for API and database, one end-to-end test for the main flow, then roll out gradually while watching errors and the metric the feature is meant to move.
Follow-up
- Two requirements conflict; how do you resolve it?
- The deadline moves up by half; what do you cut?
- After launch, how do you know whether the feature worked?
How would you optimize a slow-running application?
Medium · Problem-Solving / Case Studies
Approach
- Define slow precisely: which page or endpoint, at which percentile (p95/p99), under what load, and the target; then measure before changing anything.
- Find where the time goes: the browser network waterfall and performance panel for the front end, APM traces or a profiler for the server, split into network, application CPU, database and external calls.
- For the database, run EXPLAIN on the slow queries and look for full scans, missing or unused indexes, N+1 query patterns from the ORM, SELECT * and deep OFFSET pagination.
- Apply the fix that matches the bottleneck: indexes or query rewrites, batching, caching with a clear invalidation rule, moving work to background jobs; on the front end, smaller bundles, code splitting and fewer re-renders.
- Verify with a before/after measurement under the same load, and guard against regression with a performance budget or alert.
Follow-up
- A query is fast in isolation but slow in production; what do you check?
- The cache made it fast but users now see stale data; how do you fix that?
- How would you stop the slowdown from creeping back in?
Provide a solution for improving user engagement based on analytics data.
Medium · Problem-Solving / Case Studies
Approach
- Define engagement as a measurable metric first (weekly active users, D7/D30 retention by signup cohort, adoption of a key action) and check the event tracking that feeds it is complete and consistent.
- Find where users drop off: a funnel through the core flow and a cohort retention table, segmented by new versus returning users, platform and acquisition channel.
- Form a specific hypothesis from the biggest drop-off, and design a change that targets it rather than a generic feature.
- Test it with an A/B experiment: choose the randomisation unit, one primary metric plus guardrail metrics, a sample size from a power calculation, and a fixed duration so repeated peeking does not inflate false positives.
- Watch for novelty effects that fade, and for Simpson's paradox when segment mix differs between groups.
Follow-up
- Engagement rises but revenue falls; what do you do?
- How would you write the SQL for a weekly cohort retention table?
- How would you evaluate the change if an A/B test is not possible?
Discuss a time you had to pivot your approach mid-project due to unforeseen circumstances.
Medium · Problem-Solving / Case Studies
Approach
- State the original plan and the signal that broke it, with a date and evidence: a failed benchmark, a deprecated dependency, a changed requirement.
- Show how you compared options: cost to finish the current path against cost to switch, ignoring sunk cost, and which risks each option retired.
- Describe how you communicated it: who you told, how quickly, and how scope or timeline was renegotiated.
- Report what you salvaged from the earlier work and the outcome in numbers, in the first person: what I decided and what it delivered.
- Name the earlier check (a spike, a load test, a dependency review) that would have surfaced the problem sooner.
Follow-up
- Looking back, when should you have spotted the problem?
- Did anyone disagree with the pivot, and how did you handle it?
- What would have happened if you had kept the original plan?
Describe a situation where you had to debug a critical issue in production.
Medium · Problem-Solving / Case Studies
Approach
- Open with impact in numbers: what broke, for how many users, and how it was detected (an alert, a customer report).
- Show mitigation before diagnosis: I rolled back, flipped a feature flag or shed load to stop the damage, then investigated.
- Walk the diagnosis in order: narrow the scope from dashboards, logs and traces; line the start time up against deploys, config changes, traffic or a dependency; reproduce; then confirm the root cause rather than the first plausible trigger.
- Explain the fix and how you verified it (error rate back to baseline, a regression test that fails without the fix).
- End with the follow-through: the postmortem actions you owned, such as a missing alert, a test, a safer rollout step.
Follow-up
- Why did tests and monitoring not catch it before users did?
- How did you tell the real cause from a coincidence in timing?
- What did you change so this class of failure cannot recur?
Suggested practice checklist
The plan follows the three reported stages. Day 1 builds your project inventory, days 2-6 cover web fundamentals, JavaScript, MySQL, coding and design, and day 7 is behavioral stories and a full mock.
Day 1 — Map the loop and inventory your projects
- Write the three reported stages and, beside each, what you need to bring: a career narrative, project depth, and stories.
- Pick two projects and write for each the architecture, your contribution, one bug you diagnosed, one trade-off and one measured outcome.
- Compare the stack candidates describe (JavaScript, Python or Ruby, SQL, REST, with React, Vue.js, AWS or Azure as extras) with your experience and mark the gaps.
Deliverable: A one-page loop map, two project sheets, and a list of stack gaps to close this week.
Day 2 — Web protocols, state and REST
- Answer aloud the web protocols question, naming HTTP/1.1, HTTP/2, HTTP/3, WebSocket and TLS and when each applies.
- Answer aloud how you manage state in a web application, separating server, UI, URL and persisted state.
- Sketch a REST API for one resource of your choice with endpoints, status codes, idempotent methods, pagination and error format.
Deliverable: Spoken answers to the protocol, state and REST questions, plus a one-page REST API sketch.
Day 3 — JavaScript, HTML5 and building a feature
- Refresh closures, the event loop, promises and async/await, and write a short example of each.
- Build a small search box in plain JavaScript and HTML5 that debounces input and fetches from an API, handling loading and error states.
- Answer aloud how you would build a feature from a set of user requirements, from clarifying questions to rollout.
Deliverable: Working code for the search box, a one-page JavaScript cheat sheet, and a spoken feature-building answer.
Day 4 — MySQL, queries and slow applications
- Write by hand a join, a GROUP BY with HAVING, and a window-function query for a schema you know.
- Take one slow query, read EXPLAIN, add a composite index and record the plan before and after.
- Answer aloud how you would optimize a slow-running application, working from measurement to fix.
Deliverable: Three handwritten queries, a before-and-after EXPLAIN note, and your spoken relational database and slow-application answers.
Day 5 — Coding aloud
- Solve the longest substring without repeating characters question with a sliding window and a hash map, in JavaScript or Python.
- Write binary search iteratively, then handle duplicates and an empty array.
- Reverse a linked list iteratively and recursively, then do one tree or graph traversal with BFS and DFS.
- Explain how you would sort a dataset too large for memory, including external merge sort.
Deliverable: Tested solutions for the substring, binary search, linked list and one tree or graph problem, plus a spoken external-sort explanation.
Day 6 — System design and production problems
- Design a real-time data processing system: ingestion, queue, workers, storage and the read path, with failure handling.
- Answer aloud the microservices, fault tolerance and scalability questions, using your own architecture trade-offs as examples.
- Write up a production debugging story: symptom, first checks, cause, fix and prevention.
- Outline how you would improve user engagement from analytics data: events, funnel, hypothesis and how you would test it.
Deliverable: One design diagram with failure modes, spoken design answers, a production debugging write-up and an analytics-to-action outline.
Day 7 — Behavioral stories and full mock
- Write and rehearse stories for the challenging project, prioritisation, collaboration, advocating for a technical decision, conflict and mid-project pivot questions.
- Check each story states your decision, the alternatives, and an outcome you can measure.
- Run a full mock: a short intro as for the first call, one project deep dive, one coding problem and two behavioral questions.
Deliverable: A story bank covering all six behavioral prompts and one recorded or peer-reviewed mock loop with notes.
Behavioral stories for the third stage
Candidates report that the third stage covers interpersonal skills and cultural fit. The leadership themes reported are facilitating discussion and building consensus, mentoring junior engineers, and handling conflict or differing opinions. Prepare real stories that show your decision, your reasoning and a result.
- Can you describe a time when you led a project and what the outcome was?
Describe your experience with relational databases and provide examples of queries you have written.
Medium · Technical / Domain Questions
Approach
- Choose one real system and describe its schema briefly: the main tables, the keys, and the relationships such as one-to-many or a join table. Name actual tables so the answer is concrete. MySQL is the database candidates list for this role, so say which version and storage engine you used if you know them.
- Walk through two or three queries you actually wrote, one per shape: a multi-table JOIN with filters, an aggregation with GROUP BY and HAVING, and one using a subquery, CTE or window function. Mention that CTEs and window functions need MySQL 8.0 or later. Explain why you chose INNER or LEFT JOIN, and what happens when a WHERE condition on the right-hand table removes the NULL rows a LEFT JOIN produced.
- Include one performance story: you ran EXPLAIN, saw a full table scan or a filesort, added a composite index with equality columns first and then the range or sort column, and re-ran it to compare. Note the cost of an extra index on writes.
- Cover correctness: transactions and what InnoDB's default isolation level (REPEATABLE READ) gives you, parameterised queries against SQL injection, and how you ran a schema change on a large table. Say only what you did, and name any gap plainly with how you would close it.
Follow-up
- How would you speed up a query that joins two tables with millions of rows each?
- Given an index on (a, b), which queries does it help and which does it not?
- When would you denormalise a table, and what do you give up?
Can you describe a challenging project and how you overcame obstacles?
Medium · Behavioral / Leadership
Approach
- Choose a project where you made decisions and the obstacle was real: a migration, a performance problem, unclear requirements or a dependency that slipped. A story where the obstacle was a tight deadline and you worked longer shows little.
- Open with a two-sentence situation, then name the obstacle precisely, for example a query that degraded as data grew or an API contract the front end could not meet. Spend most of the answer on what you tried, including the approach that failed and why.
- State the result with something checkable: latency before and after, a defect rate, a deadline met, or a process that changed. Close with what you would do differently.
- Keep the story at the level of your own actions. Saying 'we' throughout leaves it unclear what you did, so say 'I' for your decisions and name the teammates who contributed.
Follow-up
- What was the hardest decision in that project, and what alternatives did you reject?
- How did you know your fix worked and not that conditions changed?
- What would you do differently if you ran it again?
How do you prioritize tasks when working on multiple projects?
Medium · Behavioral / Leadership
Approach
- Give a real instance, not only a framework: list the competing items you had at that moment, such as a production defect, a feature deadline and a code review backlog.
- Show your criteria: user or revenue impact, urgency and cost of delay, what blocks other people, and effort. Say how you checked with the product manager or other stakeholders rather than guessing.
- Say what you deferred or dropped and how you told the affected people, so the trade-off was visible to them.
- Describe how you re-evaluated when something changed mid-week, since priorities rarely stay fixed. A weak answer claims you do everything or that you simply work harder.
Follow-up
- Tell me about a time you got the order wrong, and what it cost.
- What do you do when two stakeholders each say their item is the top priority?
- How do you protect time for refactoring or technical debt?
Give an example of how you have successfully collaborated with a team.
Medium · Behavioral / Leadership
Approach
- Choose a collaboration with cross-functional partners, since candidates describe working with product managers, designers and other engineers. Name the goal and who was involved.
- Show your own contribution and the mechanisms you used: a short design write-up, an agreed API contract between front end and back end, early code review, or a shared task board.
- Include one friction point, such as a requirement that changed or two people with different approaches, and say how you handled it.
- End with the outcome and what the team did better afterwards. Avoid a story where everything went smoothly or where you did the work alone.
Follow-up
- What was your specific contribution compared with the rest of the team?
- How did you handle a teammate who was not delivering?
- What would you change about how that team worked?
Describe a time when you had to advocate for a technical decision.
Medium · Behavioral / Leadership
Approach
- State the decision and the alternatives in one or two sentences, for example a library or architecture choice, a database design or whether to refactor now.
- Show the evidence you gathered: a prototype, a benchmark, incident history or a cost estimate. Show you tailored the argument to the audience, with delivery and risk for a product manager and maintainability for engineers.
- Describe how you handled the pushback: the objection you heard, how you addressed it, and any compromise you made.
- Give the outcome honestly, including if you were partly wrong or overruled and how you committed to the final call. A story where you simply won and everyone else was mistaken reads poorly.
Follow-up
- What was the strongest argument against your position?
- What would have changed your mind?
- How did you act after the decision went another way?
How do you deal with conflict within a team?
Medium · Behavioral / Leadership
Approach
- Pick a conflict about substance, such as a code-review disagreement, an API design dispute or a priority clash, and keep it professional with no villain.
- Describe your steps in order: understand the other person's position first, usually one-to-one; find the shared goal; bring data or a small experiment; and agree who decides and how before escalating.
- Show your own part honestly, including something you changed after listening, and describe how the working relationship stood afterwards.
- State the concrete resolution and result. Saying you avoid conflict, or that it is always the other person's fault, are the two answers that fail.
Follow-up
- What if the other person still disagreed after you showed the data?
- When have you escalated a disagreement, and how did you decide to?
- How do you handle a disagreement with someone more senior?