Interview guides · Activision Blizzard
Activision Blizzard Software Engineer Interview Guide
Activision Blizzard Software Engineer interview prep: online assessment, C++ and Python fundamentals, coding, system design and panel rounds.
The 60-second brief
Activision Blizzard makes games including Call of Duty, World of Warcraft, Diablo and Overwatch, and runs Battle.net, the online platform players use to sign in, find matches and connect with each other. Software Engineers there split roughly between studio work (client and engine code, real-time multiplayer networking, cross-platform UI) and platform work (backend services, microservices and databases behind Battle.net and live games). Candidates report that which side you interview for shapes the questions: platform teams may test distributed systems and standard algorithm problems, while game engine roles put more weight on C++ memory management and multithreading. Reported studio locations include Irvine, Santa Monica, Vancouver and Dublin, and stages can vary by location and team.
This guide is for candidates interviewing for a Software Engineer role at Activision Blizzard, from associate to senior level, on either a game studio team or a platform team such as Battle.net. It covers the four reported stages and all twenty reported questions: C++ memory, virtual dispatch and parameter passing, Python garbage collection, thread synchronization, HTTP and gRPC, SQL indexing, Docker, Redis sessions and caching, matchmaking design, five algorithm problems, and the project, debugging and behavioral prompts. The requirements candidates describe ask for strength in one of C++, Java, Python or C#, plus data structures, OOP, Git or Perforce and debugging. Docker, SQL/MySQL, AWS or Azure, game engines and low-latency networking are listed as nice-to-haves.
Candidates report four stages over about 3-5 weeks: a recruiter screen, an online assessment (sometimes a live phone screen with an engineering lead instead), technical interviews mixing live coding with knowledge checks, and a final panel of consecutive virtual interviews.
Focus areas
- Programming problem solving
- Python
- Algorithms
Overview
The reported questions fall into four groups, and each needs a different kind of preparation. Language fundamentals (stack versus heap, vtables, Python's garbage collector, pass-by-value versus reference versus pointer, thread synchronization) are explanation questions: a good answer gives the mechanism, then what it costs, then what you would do about it in real code. Algorithm problems (expression validation, maximum subarray, grid shortest path, directed cycle detection, cutting a quadratic algorithm down) need code that works and handles edge cases. Web and data questions (HTTP and gRPC, SQL indexing on a large player table, Docker, Redis sessions, matchmaking under peak load) mix quick recall with open-ended design. Project, debugging and behavioral prompts need prepared stories.
Candidates report questions on memory management, dynamic dispatch and runtime internals alongside the coding work, and quick-fire questions on HTTP methods, status codes and basic SQL. If you are interviewing for an engine role, also review smart pointers and the less common topics candidates mention, such as cache locality and custom allocators. If your strongest language is Python or Java, still be able to say what a C++ vtable call and a heap allocation cost, because both appear among the reported questions.
The reported design topics include a matchmaking service under peak load, session state and caching in Redis, slow queries over millions of player records, and containerized microservice deploys. Candidates also mention a question on TCP versus UDP for game packets and one on a schema for a global player inventory with high read and write throughput. Practise each design as a short sketch you can talk through: the request path, where state lives, how it splits across machines, and what happens when a dependency fails. For mid-level and senior candidates, candidates report distributed architecture, scalability, and latency and consistency trade-offs as expected topics.
The final panel covers system design, debugging, project deep dives and behavioral discussion. Candidates report that resume projects get examined in detail and that vague product summaries go over badly. Before the loop, pick one project you can explain down to the schema and the failure handling, have one production debugging story with a root cause you can explain, and know which Activision Blizzard product or team you are interviewing for and why.
The Activision Blizzard interview process
These are the four stages candidates report. Exact steps vary by studio and team, and some candidates get a live phone screen with an engineering lead in place of the automated assessment.
Recruiter Screening
Candidates report a first call with a recruiter about your background, project history, interest in the company and logistics such as location. Candidates suggest using this call to ask about team structure, tech stack and interview format, so find out whether you are interviewing for a studio team or a platform team like Battle.net, which language the coding stages expect, and whether your next step is the automated assessment or a live screen. Come with a short background that names the languages and systems the job posting lists.
What to demonstrate
- Whether your background and project history match the posting
- Your interest in Activision Blizzard and the specific team
- Logistics such as location
How to prepare
- Write a short spoken summary of your background that uses the posting's own stack terms (C++, Java, Python or C#, plus any Docker, SQL or engine experience).
- Write a specific answer to why Activision Blizzard: one product or team (Battle.net, a franchise you play) and one engineering problem there that matches your experience.
- Write down the questions to ask: studio or platform team, language for the coding stages, assessment or live screen next, and the format of the final panel.
Online Assessment
Candidates describe this stage as automated: algorithmic coding challenges, automated syntax tests, or a recorded technical video response, run on platforms such as HackerRank or HireVue. Some candidates instead get a live technical phone screen with an engineering lead. For the coding part, write solutions that pass hidden test cases, which means handling empty input, all-negative values, unreachable targets and overflow without anyone prompting you. For syntax tests, review your main language's details. For a video response, practise explaining a concept clearly to a camera with no one asking follow-ups.
What to demonstrate
- Working, correct code on algorithm problems under automated tests
- Syntax and language-detail knowledge in your chosen language
- Explaining a technical concept clearly in a recorded or live answer
How to prepare
- Practise the reported algorithm problem types (string validation, maximum subarray, grid BFS, directed cycle detection) in a plain browser editor with no autocomplete, and write your own edge-case tests before you submit.
- Write a one-page cheat sheet of language details for your main language: C++ references and const, Python mutability and default arguments, Java equals and hashCode.
- Record yourself explaining stack versus heap or Python's garbage collector, then watch it back and cut the filler.
Technical Interviews
Candidates describe this stage as conversations with a hiring manager and engineers on the team, mixing live coding with questions that test what you know. Expect to code in a shared editor and to answer knowledge questions in between. For live coding, say your approach and its complexity before you type, name edge cases early, and run a small example through your code at the end. For knowledge questions, give the mechanism and its cost in a few sentences, then stop.
What to demonstrate
- Live coding: working, correct code with stated complexity
- Explaining your reasoning out loud while you code
- Technical knowledge checks in the areas the role covers
How to prepare
- Practise saying your approach out loud while solving the cycle-detection and grid shortest-path problems, including the brute force you are improving on.
- Make flashcards for status codes (200, 201, 204, 301, 304, 400, 401, 403, 404, 409, 429, 500, 502, 503) and HTTP method idempotency, since candidates report quick questions on HTTP, status codes and basic SQL.
- Practise short spoken answers on vtables, smart pointers, pass-by-reference versus pointer, and deadlock prevention, each ending with a concrete example.
- Practise a short answer on TCP versus UDP for game packets: ordering and head-of-line blocking in TCP, reliability you build on UDP with sequence numbers and acks, which packets need it, and WebSockets for server push.
Final Panel Loop
Candidates describe a run of consecutive video interviews that take in system design, debugging a problem, a walk through your past projects, and behavioral questions. Because the sessions follow one another closely, have your stories and designs ready in advance rather than building them on the spot. For design, work from requirements to components to partitioning to failure handling. For the project deep dive, candidates report that concrete engineering detail and metrics matter more than product description. For debugging, walk through a real investigation in order.
What to demonstrate
- System design: components, data placement, scaling and failure handling
- Debugging method on a real or posed production problem
- Depth of ownership in a past project: your decisions and their trade-offs
- Behavioral discussion: how you work with others and make decisions
How to prepare
- As design practice, write a one-page matchmaking design (ticket intake, pools split by region and mode, matcher workers, game server allocation, disconnect handling) and a Redis session and caching design with its failure paths.
- Write a walk-through for one resume project: architecture, your specific decisions, alternatives you rejected, numbers, and what you would change.
- Write a production-bug story in order: detection, mitigation, narrowing the cause, root cause, and the test or alert you added.
- Prepare a STAR story for disagreement, for tight deadlines or unclear requirements, and for why this company.
Where candidates lose points
Explaining stack versus heap or vtables at textbook level, without saying what the allocation or the virtual call costs or who owns the memory.
For each language fundamentals question, practise three parts: the mechanism (vptr, slot load, indirect call; operator new and the allocator), the cost (cache misses, no inlining, fragmentation), and the practical fix (final, CRTP, unique_ptr, pool allocators). Do the Python garbage collector question the same way: reference counting, the cyclic collector, then pymalloc arenas.
Fumbling quick fundamentals such as 401 versus 403, which HTTP methods are idempotent, why a query ignores an index, or why a game sends some packets over UDP.
Candidates report rapid questions on HTTP methods, status codes and basic SQL, and list networking protocols among the topics. Make flashcards for status codes, method idempotency, REST versus gRPC, TCP versus UDP (head-of-line blocking, reliability built on UDP with sequence numbers and acks), and index-disabling patterns (a function on the column, a LIKE pattern that starts with %, large OFFSET), and go through them daily until each answer is one sentence.
Code that fails the obvious hidden tests: Kadane starting at 0 on an all-negative array, or directed cycle detection with a single visited set.
For every coding problem in this guide, write the edge-case list before you write code (empty input, all negative, unreachable target, disconnected graph, self-loop) and run each case by hand at the end. In grid BFS, mark cells when you enqueue them so duplicates do not push a large grid past time or memory limits. This matters most in the automated assessment, where nobody prompts you.
Giving the project deep dive as a product summary, crediting everything to the team, with no numbers and no rejected alternatives.
Prepare one project to the level of schema, failure handling and deploy. Name two or three decisions you made, the alternative you rejected for each, and measured results. Say 'I' for your own work.
Sketching matchmaking or Redis caching as a happy path with no answer for a player landing in two matches, a hot key expiring, or Redis going down.
For every design topic in this guide, write down its failure paths ahead of time: single-owner pools or atomic ticket claims for matchmaking; stampede protection, a database fallback and failover for Redis; cross-shard trades for the player inventory. Raise them yourself before the design is complete.
Questions & practice
Explain the difference between stack and heap memory, and how dynamic memory allocation works in C++.
Medium · Core Languages & Computer Science Fundam
Approach
- Stack: automatic storage, one per thread. A function's frame is reserved by moving the stack pointer and freed when the scope exits, so allocation is nearly free and cache-friendly. The size is fixed when the thread is created, so deep recursion or large local arrays overflow it.
- Heap (free store): new calls operator new, which goes to the allocator (malloc and its free lists or arenas, which get pages from the OS through brk or mmap), and then runs the constructor. delete runs the destructor, then frees the memory. The lifetime is explicit, and costs include allocator bookkeeping, possible locking, fragmentation and poor locality.
- Ownership in modern C++: RAII; unique_ptr for sole ownership at zero overhead; shared_ptr with an atomic reference count and a control block (make_shared puts both in one allocation); weak_ptr to break reference cycles.
- Edge cases to name: returning a pointer or reference to a local (it dangles), mixing new[] with delete (undefined behavior), double free, and leaks when an exception skips a manual delete. Each one is a reason to use RAII.
- Performance angle: in hot loops, avoid per-frame heap allocation by calling vector::reserve, reusing buffers, or using pool or arena allocators that reset every frame.
Follow-up
- How would you find a memory leak in a large C++ codebase (AddressSanitizer or LeakSanitizer, Valgrind, allocation tracking in a custom allocator)?
- Why might a game use a per-frame arena allocator, and what does it give up?
- What does make_shared save compared with shared_ptr<T>(new T)?
What are virtual functions and vtables, and how does polymorphism impact runtime performance?
Medium · Core Languages & Computer Science Fundam
Approach
- Each class with virtual functions has a vtable, a static table of function pointers. Each object holds a hidden vptr that the constructor sets. A virtual call loads the vptr, loads the slot for that function, and makes an indirect call.
- Costs: one or two extra memory loads, an indirect branch that mispredicts when types are mixed in a loop, no inlining unless the compiler can devirtualize, and the vptr adds 8 bytes to every object on 64-bit, which hurts cache density.
- Put the cost in proportion: it is negligible for coarse-grained calls and noticeable when you iterate millions of mixed-type small objects every frame. Measure with a profiler before redesigning.
- Rules: give a base class a virtual destructor if objects are deleted through a base pointer; inside a constructor or destructor a virtual call resolves to the current class;
finallets the compiler devirtualize. - Alternatives: CRTP for static polymorphism, std::variant with std::visit, or grouping objects by type so each loop calls a single implementation (data-oriented layout).
Follow-up
- With multiple inheritance, how many vptrs can an object have, and what does a pointer adjustment (thunk) do?
- Why is calling a virtual function from a constructor a bug in practice?
- How would you show whether virtual dispatch is a real bottleneck in a hot loop?
How do Python's memory management and Garbage Collector operate under the hood?
Medium · Core Languages & Computer Science Fundam
Approach
- CPython frees most objects through reference counting: every object has a count, and when it reaches zero the object is freed immediately and its destructor runs.
- Reference counting cannot free cycles, so a cyclic garbage collector also tracks container objects (lists, dicts, class instances) and frees groups reachable only from each other. Through CPython 3.13 it uses three generations with allocation thresholds (gc.get_threshold); 3.14 replaced that with an incremental collector with young and old generations. Since 3.4 (PEP 442), cycles containing del are collected.
- Allocation: pymalloc handles small objects (512 bytes or less) using arenas, pools and size-class blocks. An arena goes back to the OS only when it is completely empty, so process memory often stays high after you free many small objects. Larger blocks come from malloc directly and may be returned.
- Other details worth mentioning: small integers from -5 to 256 are cached, some strings are interned, and the GIL is what makes the non-atomic refcount updates safe in the standard build.
- Leaks in Python are usually references that stay alive (global caches, closures, saved tracebacks, unbounded dicts). Find them with tracemalloc snapshots, gc.get_referrers and objgraph, and fix them with weakref or bounded caches.
Follow-up
- Why might RSS stay high after you delete millions of small objects, and what would you do about it?
- When would you call gc.disable() or gc.freeze(), for example in a forking server?
- How would you track down memory that keeps growing in a long-running Python service?
What are the core differences between pass-by-value, pass-by-reference, and pass-by-pointer?
Medium · Core Languages & Computer Science Fundam
Approach
- By value: the callee gets its own copy (or a moved-from object), and changes do not reach the caller. Cost grows with the copy for large types. Use it for small types, and for sink parameters where you take by value and then std::move into place.
- By reference (T&): an alias that cannot be null or reseated. Use const T& for large read-only inputs. A non-const lvalue reference cannot bind to a temporary, but const T& and T&& can.
- By pointer: the address is copied, so the pointer itself is passed by value. It can be null and can be reseated, and the & at the call site makes mutation visible. Use it when the argument is optional or for C interfaces.
- Pitfalls: passing a derived object by value to a base parameter slices it; returning a reference or pointer to a local leaves it dangling; pointer parameters need a documented ownership rule.
- Contrast with managed languages: Java and Python pass object references by value. Rebinding the parameter does not affect the caller, but mutating the object does.
Follow-up
- What is object slicing, and how do you prevent it?
- When would you take a std::string parameter by value instead of const std::string&?
- In Python, why does appending to a list parameter change the caller's list but assigning a new list does not?
Explain the concept of thread synchronization, race conditions, and how to prevent deadlocks in multithreaded
Medium · Core Languages & Computer Science Fundam
Explain the concept of thread synchronization, race conditions, and how to prevent deadlocks in multithreaded systems.
Approach
- A race condition: two threads access shared state without ordering and at least one of them writes. A read-modify-write such as
hp -= damagefrom two threads loses updates. In C++, a data race is undefined behavior, not just a wrong value. - Tools, cheapest first: std::atomic with fetch_add or compare-exchange for single values; std::mutex with lock_guard or scoped_lock for invariants spanning several fields; shared_mutex for read-heavy data; condition variables for waiting on a state change.
- Deadlock requires all four Coffman conditions: mutual exclusion, hold-and-wait, no preemption and circular wait. Prevent it by breaking one: a global lock order, std::scoped_lock to take several locks at once, try_lock with backoff, and never calling unknown code while holding a lock.
- Design-level fixes: give each piece of shared state a single owner thread and send it messages or jobs, keep critical sections small, and copy data out before slow work.
- Related hazards to name: livelock, priority inversion, and false sharing (two hot atomics on one cache line; fix it with alignas(64) padding).
Follow-up
- A server hangs in production and you suspect a deadlock. What do you collect (thread dumps, gdb
thread apply all bt) and how do you read it? - When is an atomic not enough, so you need a mutex?
- How would ThreadSanitizer help here, and what can it miss?
Implement an algorithm to validate string expressions or perform complex string manipulations efficiently.
Medium · Algorithms & Applied Coding
Approach
- Bracket validation: scan once with a stack. Push opening characters; on a closing character, check that the stack is not empty and its top is the matching opener, then pop. The string is valid only if the stack is empty at the end. O(n) time, O(n) space.
- Evaluating arithmetic: tokenize first (multi-digit numbers, whitespace, unary minus), then use shunting-yard with an operator stack and a value stack, or recursive descent with one function per precedence level (expression, then term, then factor). Handle division by zero and overflow explicitly.
- For the variant where '*' can stand for '(' , ')' or nothing: track the minimum and maximum possible open count in one greedy pass. This is O(n) time and O(1) space.
- For string manipulation in general: never build a string with += in a loop (O(n^2) in many languages). Use ''.join, StringBuilder, or std::string::reserve. Two pointers and character-count arrays cover most in-place transformations.
- Edge cases to test aloud: the empty string, only closing characters, an opener left at the end, nested and interleaved pairs, and non-ASCII input if the input is player chat.
Follow-up
- Return the index of the first error instead of a boolean.
- Extend the evaluator to support variables or function calls such as max(a, b).
- How would you validate input that arrives as a stream of chunks?
Given an array of integers representing game scores, find the contiguous subarray with the maximum sum.
Medium · Algorithms & Applied Coding
Approach
- The brute force checks every subarray: O(n^2) with running sums, O(n^3) without. State it, then improve it.
- Kadane's algorithm:
cur = max(x, cur + x); best = max(best, cur)in one pass. That is O(n) time and O(1) space, because a negative running prefix can never help a later subarray. - Initialize both values to the first element, not 0, so an all-negative array returns its largest element. Ask whether an empty subarray is allowed, since that changes the answer to 0.
- To return the bounds, record a tentative start whenever cur restarts at x, and save start and end whenever best improves.
- Use 64-bit accumulators if the scores can be large. Mention the O(n log n) divide-and-conquer version and the prefix-sum view (the maximum of prefix[j] minus the minimum earlier prefix) as alternatives.
Follow-up
- Solve it for a circular array: the answer is the larger of normal Kadane and total minus the minimum subarray, with the all-negative case handled separately.
- What if the subarray length must be at most k (prefix sums plus a monotonic deque)?
- Extend it to the maximum-sum rectangle in a 2D grid.
How would you traverse a tree or graph structure to calculate shortest path distances in a grid layout?
Medium · Algorithms & Applied Coding
Approach
- Unweighted grid, 4-directional moves: BFS from the source with a queue and a distance array. The first time BFS reaches a cell, that is its shortest distance. O(R*C) time and space. DFS does not give shortest paths.
- Mark a cell visited when you enqueue it, not when you dequeue it, or the same cell enters the queue many times and large grids hit time or memory limits. Check bounds and walls before enqueueing.
- Weighted cells: Dijkstra with a min-heap, O(V log V). With 0/1 costs, use 0-1 BFS with a deque. For a single target, A* with Manhattan distance (admissible for unit-cost 4-directional moves) expands far fewer cells, which is why game pathfinding uses it.
- Variants: multi-source BFS (start with all sources in the queue) for distance to the nearest exit or spawn; adding state to each node (row, col, walls removed) when up to k walls can be removed; parent pointers to rebuild the path.
- Edge cases: the start or target is blocked, the target cannot be reached (return -1), the start equals the target, and the grid is a single row. For a tree, the path between two nodes goes through their lowest common ancestor.
Follow-up
- Up to k obstacles can be removed. How does the state and the complexity change?
- Return the actual path, not just the distance.
- The map is huge and queried constantly. What do you precompute (hierarchical pathfinding, cached regions)?
Write a function to detect cycles in a directed graph using depth-first search (DFS).
Medium · Algorithms & Applied Coding
Approach
- Use three colors: white (not visited), gray (on the current DFS path), black (finished). An edge to a gray node is a back edge, so there is a cycle. An edge to a black node is not. O(V+E) time, O(V) space.
- Explain why the undirected trick fails: a single visited set reports false cycles on directed graphs when two paths reach the same finished node (A to B, A to C, C to B is acyclic).
- Start DFS from every white node, because the graph may be disconnected. Treat self-loops as cycles, and include nodes that appear only as edge targets.
- Python's default recursion limit is 1000, so for deep graphs write the iterative version: an explicit stack of (node, neighbor-iterator) pairs, coloring gray on push and black when the iterator is exhausted.
- Alternative: Kahn's algorithm (repeatedly remove nodes with in-degree 0). If fewer than V nodes are removed, a cycle exists, and the removal order is a valid topological order, which also answers a 'deployment order for dependent services' problem.
Follow-up
- Return the nodes in the cycle, not just true or false.
- Given services and their dependencies, output a valid deployment order, or report which services block it.
- Find every node that lies on some cycle (strongly connected components with Tarjan or Kosaraju).
Optimize an existing algorithm to reduce time complexity from to or .
Medium · Algorithms & Applied Coding
Approach
- Start by naming what the inner loop recomputes, because that tells you the fix. A membership or complement lookup becomes a hash set or map (two-sum becomes O(n)). A repeated range sum becomes a prefix-sum array. A window recomputed from scratch becomes a sliding window or two pointers.
- Pairwise comparisons over values that can be ordered: sort first, then sweep or binary search, for O(n log n). Examples are closest pair in 1D, overlapping intervals, and pairs with difference k.
- 'Next greater' or 'previous smaller' scans become a monotonic stack (amortized O(n)). Repeated top-k selection becomes a heap (O(n log k)).
- State what each change costs: hash maps use O(n) memory and degrade under adversarial collisions, and sorting loses the original order unless you carry indices.
- Check the new version against the brute force on random small inputs before claiming it is correct. In real code, also profile, because constant factors and cache locality can matter more than the big-O change.
Follow-up
- Can you do it with O(1) extra space?
- Why is O(n log n) the lower bound for element distinctness with comparisons, and how does hashing get around it?
- How does your solution change if the input arrives as a stream?
How does SQL indexing work, and how would you optimize a slow database query handling millions of player recor
Medium · Web Services, Databases & System Design
How does SQL indexing work, and how would you optimize a slow database query handling millions of player records?
Approach
- How it works: a B-tree index keeps keys sorted, so equality and range lookups take O(log n) and ordered scans are cheap. In MySQL InnoDB the table is clustered on the primary key, and a secondary index stores the PK, so a lookup that is not covered makes a second trip to the table.
- Method: capture the slow query with the slow query log, then run EXPLAIN or EXPLAIN ANALYZE. Look for type=ALL (full scan), a high rows-examined count, 'Using filesort' or 'Using temporary', and an index that exists but goes unused.
- Fix it with a composite index whose order matches the query: equality columns first, then the range or ORDER BY column. For example,
WHERE region = ? AND last_login > ? ORDER BY last_loginuses (region, last_login). Add selected columns to make it covering when the row lookups dominate. - Patterns that disable an index: a function on the column (
DATE(created_at) = ...), a LIKE pattern starting with %, implicit type conversion, OR across different columns, and large OFFSET pagination (use keyset pagination:WHERE id > ? LIMIT n). - Trade-offs and next steps: each index slows writes and uses buffer pool memory. Past indexing, use read replicas, a cache for hot rows, partitioning by date, or archiving cold player data.
Follow-up
- Why might the optimizer ignore an index you added?
- How do you add an index to a very large table without blocking writes (online DDL, gh-ost or pt-online-schema-change)?
- Is an index on a low-cardinality column such as platform worth it?
Stop tag and share joins from fanning out a page
Medium · join fan-out · semi-joins · many-to-many
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(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(3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
- Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
- Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
- Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.
Follow-up
- The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
- A resource can be shared with the same user twice under different permissions. Does your count change, and should it?
Explain the main HTTP methods, status codes, and the key differences between REST and gRPC.
Medium · Web Services, Databases & System Design
Approach
- Methods: GET and HEAD are safe and idempotent; PUT replaces a resource and is idempotent; DELETE is idempotent; POST creates or triggers an action and is not idempotent; PATCH applies a partial update and is not guaranteed idempotent; OPTIONS handles CORS preflight.
- Status codes by class: 200, 201 Created, 204 No Content; 301 vs 302, 304 Not Modified; 400, 401 (not authenticated) vs 403 (authenticated but not allowed), 404, 409 Conflict, 429 Too Many Requests; 500, 502 Bad Gateway, 503 Unavailable, 504 Gateway Timeout.
- REST: resource URLs, usually JSON, works with HTTP caching and browsers, readable with curl, and loosely typed unless you add OpenAPI.
- gRPC: a Protocol Buffers contract with generated stubs, binary encoding, HTTP/2 multiplexing, deadlines, and client, server or bidirectional streaming. Browsers need grpc-web or a proxy, and the traffic is harder to inspect by hand.
- When to use each: REST for public or browser-facing APIs, gRPC for internal low-latency service-to-service calls and streaming. For non-idempotent POSTs, make retries safe with an idempotency key.
Follow-up
- A client retries a purchase POST after a timeout. How do you stop it charging twice?
- How do you change a protobuf message without breaking old clients (new field numbers, never reuse a removed one)?
- Which status code do you return for rate limiting, and which headers go with it?
What strategies would you use to design a distributed matchmaking service under peak server loads?
Medium · Web Services, Databases & System Design
Approach
- Pin down requirements: party size, game mode, region and latency limits, how skill is measured, and the target trade-off between match quality and wait time. Ask for peak tickets per second, because that sizes everything else.
- Components: a ticket API that accepts a party's request; ticket pools split by (region, mode), with skill buckets inside each; matcher workers that each own a pool and form matches, widening the allowed skill gap as wait time grows; an allocator that reserves a game server; and a push channel (WebSocket) that tells players where to connect.
- Correctness under load: one player must never land in two matches. Give each pool a single owner (a lease or a consistent hash on the pool key), or claim tickets atomically (a Redis Lua script or compare-and-set). Make match assignment idempotent so retries cannot double-allocate.
- Peak handling: scale matcher workers horizontally by pool; apply backpressure at intake; give tickets a TTL so stale tickets expire; keep a warm server buffer and autoscale the fleet; degrade by widening skill windows rather than failing requests.
- Failure paths: a player cancels or disconnects after the match forms (requeue the others at the front), server allocation fails (retry another region), or a matcher crashes (another worker takes over the lease). Monitor queue time p50 and p95 and the skill spread per match.
Follow-up
- How do you handle parties of different sizes filling a fixed team size?
- A region's pool is tiny at 4 a.m. What do you do to queue times without wrecking match quality?
- Where would you store ticket state, and what happens if that store loses a node?
Explain the role of Docker and containerization in modern microservices deployment pipelines.
Medium · Web Services, Databases & System Design
Approach
- Mechanism: an image is a stack of read-only filesystem layers built from a Dockerfile. A container is an ordinary process isolated with Linux namespaces (pid, net, mount) and limited with cgroups. It shares the host kernel, which is why it starts faster and weighs less than a VM.
- Place in the pipeline: CI builds the image once, tags it with the commit SHA and pushes it to a registry. The same artifact then moves through dev, staging and production, with configuration and secrets injected at runtime, so what you tested is exactly what runs.
- Orchestration: Kubernetes or ECS schedules containers, restarts failed ones, routes traffic only after readiness probes pass, and does rolling or blue-green deploys. Rolling back means redeploying the previous tag.
- Good image practice: multi-stage builds to keep compilers out of runtime images, ordering layers so dependency installs stay cached, small pinned base images, running as non-root, and one main process per container.
- Limits to mention: the shared kernel is a weaker security boundary than a VM; stateful services need volumes or managed storage; builds for other platforms need care.
Follow-up
- Why does the order of Dockerfile instructions affect build time?
- A new image passes CI but fails in production. How do you roll back, and what tells you to?
- What is the difference between a liveness probe and a readiness probe, and what goes wrong if you mix them up?
How do you manage session state and caching using technologies like Redis in high-throughput backend services?
Medium · Web Services, Databases & System Design
Approach
- Sessions: store an opaque token mapped to a Redis hash of session data with a TTL (EXPIRE), refreshed on activity for sliding expiry. Compare this with stateless JWTs, which avoid the lookup but make revocation hard unless you keep a denylist.
- Caching pattern: cache-aside by default. On a read, try Redis, and on a miss load from the database and SET with a TTL. On a write, update the database, then delete the key; deleting is safer than updating the cached value, which can race. Use write-through when reads must see writes immediately.
- Failure modes to name: a stampede when a hot key expires (fix it with a single-flight lock or early refresh, and add jitter to TTLs); repeated lookups for missing rows (cache the negative result briefly); hot keys (local in-process cache); memory pressure (maxmemory with an allkeys-lru or volatile-ttl policy).
- Availability: replicas with Sentinel or Redis Cluster (16384 hash slots, multi-key commands only within one slot); RDB or AOF persistence if losing sessions is unacceptable; when Redis is down, fall back to the database with rate limiting rather than letting every request hit it.
- Use the right data structure: hashes for sessions, INCR with EXPIRE for rate limits, sorted sets for leaderboards. ZADD is O(log N), a range read is O(log N + M) for M returned entries, and ZRANGE with REV replaces the deprecated ZREVRANGE.
Follow-up
- A player updates their profile and still sees the old one. Walk through how cache-aside can cause that and how you fix it.
- How do you keep players logged in through a Redis failover?
- Design a global leaderboard with sorted sets. What happens at tens of millions of entries?
Walk through the architecture of a complex project on your resume, detailing your specific design choices and
Medium · Behavioral & Architecture Discussion
Walk through the architecture of a complex project on your resume, detailing your specific design choices and trade-offs.
Approach
- Structure it top-down: the problem and its scale (users, requests, data size you can share), the components and how a request flows through them, then what you personally owned. Say 'I' for your decisions and 'the team' for the rest.
- Pick two or three real decisions and give each one the alternative you rejected and why. For example, a queue instead of synchronous calls, MySQL instead of a document store, or a cache with a TTL instead of read replicas.
- Be ready to go two levels deeper on any component: the schema and indexes, what happens when a dependency times out, how you deployed and rolled back, how you tested it, and what you monitored.
- Close with results in numbers (latency, error rate, cost, crash rate) and one thing you would redesign now. Candidates report that concrete engineering detail counts for more here than a summary of what the product does.
- Draw it while you talk if there is a whiteboard, and keep the same component names throughout so the listener can follow.
Follow-up
- What breaks first if traffic grows ten times?
- Which decision would you reverse today, and what did it cost you?
- How did you know the system was healthy after launch?
Describe a situation where you encountered a critical production bug. How did you debug it, and what measures
Medium · Behavioral & Architecture Discussion
Describe a situation where you encountered a critical production bug. How did you debug it, and what measures did you take to prevent recurrence?
Approach
- Situation in numbers: what broke, who was affected, how it was detected (an alert, player reports, a dashboard), and how severe it was.
- Mitigate before you investigate: roll back, turn off a feature flag, or shed load. Say this explicitly, because restoring service comes before finding the cause.
- Debugging sequence: what changed and when (deploys, config, traffic, dependencies), then logs, metrics and traces around the start time, then narrow the cause by bisecting (one region, one build, one shard), then a hypothesis you confirmed by reproducing it.
- Explain the root cause technically and separate it from the trigger. For example, the deploy triggered it, but the cause was an unbounded retry loop or a race on shared state.
- Prevention: a regression test, an alert that would have fired earlier, a postmortem with owned action items, and a guardrail such as a canary deploy. The story fails if it ends at the rollback with no root cause or no personal role.
Follow-up
- How did you rule out coincidence and confirm that was the cause?
- What would have caught this before production?
- How did you communicate with other teams while it was going on?
Suggested practice checklist
Each day covers one group of the reported questions, ordered to match the loop: language fundamentals and coding first for the assessment and technical interviews, then web, networking, data and design, then the project and behavioral stories for the final panel.
Day 1 — C++ memory, dispatch and parameter passing
- Write short spoken answers on stack versus heap, smart pointers and new/delete, and record yourself giving them.
- Explain a virtual call step by step (vptr, slot, indirect call), then list its costs and two alternatives (final, CRTP or std::variant).
- Write a small C++ example that shows object slicing and a dangling reference, then fix both.
Deliverable: Three recorded answers (memory, vtables, parameter passing) and one C++ file showing slicing and dangling-reference fixes.
Day 2 — Python runtime and concurrency
- Explain CPython reference counting, the cyclic collector and pymalloc. Then create millions of small objects, delete them, and compare process RSS before and after with psutil.Process().memory_info().rss, using tracemalloc only to confirm the Python objects were freed. Note why one big list can differ: its pointer array comes from malloc, not pymalloc.
- Write a racy counter with two threads, show the lost updates, then fix it once with a mutex and once with an atomic or lock-free approach.
- Write a two-lock deadlock, then fix it with a lock order and with std::scoped_lock (or the equivalent in your language).
Deliverable: A Python memory notes page with the RSS and tracemalloc readings, plus a concurrency file with the race, the deadlock and both fixes.
Day 3 — Arrays and strings under a timer
- Solve bracket validation, then an arithmetic expression evaluator with precedence and unary minus, in a plain editor with no autocomplete.
- Solve maximum subarray with Kadane and return the bounds, then do the circular variant.
- Take three quadratic solutions (two-sum, pairs with difference k, next greater element) and rewrite them with a hash map, sort-and-sweep, and a monotonic stack.
Deliverable: Timed solutions to the seven problems above, each with a written edge-case list and the complexity before and after.
Day 4 — Graphs: grid paths and cycles
- Implement grid BFS with a distance array, then 0-1 BFS, then A* with a Manhattan heuristic, and compare how many cells each expands.
- Implement three-color DFS cycle detection recursively and iteratively, then Kahn's algorithm that returns a deployment order or the blocked nodes.
- Say your approach out loud before coding each problem, as you would in a live coding screen.
Deliverable: Working BFS, A* and cycle-detection code, plus a test file covering an unreachable target, self-loops and disconnected graphs.
Day 5 — Web, networking, SQL and containers
- Make flashcards for HTTP methods, idempotency and status codes. Write a REST versus gRPC comparison and a TCP versus UDP comparison for game packets: head-of-line blocking, reliability built on UDP with sequence numbers and acks, which packets need it, and WebSockets for push.
- On a local MySQL table of synthetic player rows, run EXPLAIN on a slow filter-and-sort query, add a composite index, and record the plan before and after.
- Work through the practice drill on tag and share joins: show how joining both tables to the same parent multiplies rows and inflates counts, then fix it by aggregating each table before the join.
- Write a multi-stage Dockerfile for a small service and explain what each layer caches and how you would roll back a bad image.
Deliverable: A flashcard deck with the REST/gRPC and TCP/UDP comparisons, an EXPLAIN comparison from before and after the index, the fan-out query with inflated and corrected counts, and a multi-stage Dockerfile with notes.
Day 6 — Design and the project deep dive
- Write a one-page matchmaking design: tickets, region and mode pools, matcher ownership, server allocation, disconnect handling and the metrics you would watch.
- Write a Redis session and cache-aside design covering TTLs, stampede protection, a leaderboard on sorted sets, and behavior during failover.
- Write a schema for a global player inventory with high read and write throughput: a (player_id, item_id) key, sharding by player_id, handling hot items, a version column for optimistic concurrency, and how a trade between players on different shards stays consistent (an escrow record or saga).
- Write your resume project walk-through with architecture, three decisions with rejected alternatives, and numbers, then say it aloud.
Deliverable: Two one-page designs, an inventory schema with its sharding and trade notes, and a rehearsed project walk-through with its decisions and metrics written out.
Day 7 — Stories and a full mock panel
- Write STAR notes for the production bug, the disagreement, and the tight-deadline stories, each with a clear personal decision and result.
- Write a specific answer to why Activision Blizzard: one product or team and one engineering problem connected to your experience.
- Run consecutive mock sessions (one coding, one design, one behavioral) with a friend or by recording yourself, then fix the weakest answer.
Deliverable: Three written STAR stories, a why-this-company answer, and notes from the mock panel with one revised answer.
Behavioural preparation
Candidates report behavioral discussion and project deep dives in the final panel, and a question about your interest in the company from the first recruiter call onward. The requirements candidates describe stress communication and working with designers, producers, QA and other engineers, so pick stories involving people outside engineering and make your own decisions clear.
- Walk through the architecture of a complex project on your resume, detailing your specific design choices and trade-offs.
- Tell me about a time a requirement from a designer or producer conflicted with a technical constraint, and what you did.
How do you handle technical disagreements or pushback from team members or project leadership?
Medium · Behavioral & Architecture Discussion
Approach
- Choose a real technical disagreement with consequences: an architecture choice, a library, or quality versus a date. Avoid one where nothing was at stake.
- Show that you understood the other side's constraint (a producer's date, a lead's maintenance worry) before arguing your own.
- Show how you settled it with evidence: a small prototype, a benchmark, a written comparison of options, or agreeing on a decision owner and escalation path.
- Give the outcome, including the case where you lost and then committed fully to the other approach, and how the working relationship went afterward.
- What sinks it: a story where the other person was simply wrong and you were simply right, or one where you went around them.
Follow-up
- Tell me about a time you were the one who was wrong.
- What would you do if the data did not settle it?
- How do you disagree with a lead or producer about scope without stalling the team?
What motivates you to work at Activision Blizzard, and how do you stay engaged with current industry trends an
Medium · Behavioral & Architecture Discussion
What motivates you to work at Activision Blizzard, and how do you stay engaged with current industry trends and technologies?
Approach
- Give two concrete reasons tied to the role: a specific product or platform (Battle.net, a franchise you know well) and the engineering problem behind it that matches your experience, such as matchmaking at scale, low-latency networking or engine performance.
- Connect it to your background: one past project that used the same kind of skill, so the motivation sounds like a career step and not only fandom.
- For staying current, name real habits and one recent result: a conference talk or engineering blog you follow, a language feature you adopted (for example C++20 ranges or Python typing), or a side project, and what you changed because of it.
- Avoid an answer that is only 'I love games', and avoid naming a title you cannot discuss if asked.
Follow-up
- Which team or product would you most want to work on, and why?
- What is something technical you learned in the last few months and actually used?
- What would you improve in one of their products from an engineering point of view?
Tell me about a time you had to deliver a feature under tight deadlines or ambiguous requirements.
Medium · Behavioral & Architecture Discussion
Approach
- Situation: what made it tight or unclear (a fixed launch date, a changing spec, missing design), and what was at risk if it slipped.
- Actions that show judgment: asking the questions that settle the most uncertainty first, writing down your assumptions and getting them confirmed, building a thin end-to-end version early, and splitting must-haves from nice-to-haves with the stakeholder.
- Show the trade-off you chose and stated openly: what you cut or postponed, the tech debt you logged, and how you kept quality on the risky parts (tests, feature flags).
- Result and follow-through: whether it shipped, what happened next, and whether you paid back the debt.
- What sinks it: a story of overtime with no decisions in it, or quietly lowering quality without telling anyone.
Follow-up
- What exactly did you cut, and who agreed to it?
- What happened to the tech debt afterward?
- What would you do if the requirements changed again a week before the deadline?