cswork / libraryOpen practice workspace

Interview guides · Zscaler

Zscaler Software Engineer Interview Guide

Zscaler Software Engineer interview guide: networking, TLS proxy, OS and DSA questions candidates report, the 5-round loop, and a 7-day prep plan.

The 60-second brief

Zscaler is a cloud security company. Its platform, the Zero Trust Exchange, runs as a globally distributed cloud service that sits inline in customer traffic instead of relying on on-premise appliances. According to the source notes, Software Engineers there build and scale the high-throughput, low-latency systems behind it: security engines, proxy architectures, cloud orchestration and fleet management, across data-plane, control-plane and frontend work.

This guide covers the Zscaler Software Engineer loop as the source notes describe it: a resume screen, an online assessment, two to three technical rounds, a techno-managerial round and an HR round. The practice follows the categories the source notes emphasise: computer networks and security protocols, data structures and algorithms, operating systems and language internals (C++ or Java track), and design. It also covers behavioural stories for the managerial and HR conversations. Frontend candidates should add JavaScript, React and browser internals on top of the networking fundamentals.

Focus areas

  • Scope every query and cache key by tenant
  • Keep money in integer minor units
  • Evolve APIs without breaking pinned SDK clients

Overview

Source notes describe Software Engineers at Zscaler working on the company's cloud security platform, the Zero Trust Exchange. It runs as a globally distributed cloud service rather than as on-premise appliances. The work they name includes security engines, proxy architectures, cloud orchestration platforms built with tools such as Temporal, and fleet management systems, spread across data-plane, control-plane and frontend teams.

That mix explains how the reported questions are weighted. Alongside algorithmic coding, reported questions go deep on computer networks and security protocols. Examples include the URL-to-page path with TCP MSS/MTU and DNS detail, TLS handshakes and how a proxy intercepts them, L4 vs L7, and IPv4 vs IPv6 headers. Operating-systems questions cover virtual memory, deadlock, and mutexes and semaphores. Language-specific questions split by track: smart pointers and memory leaks for C++ roles, and the Java memory model, garbage collection and Spring transactions for Java roles.

Source notes describe a shift for frontend roles toward JavaScript and TypeScript, React (hooks versus class components), browser rendering and the event loop. Source notes also say networking knowledge is expected across backend, frontend and platform roles, so prepare the networking fundamentals as well. For senior and staff candidates, the source notes describe design discussions covering microservices, caching, message queues and data consistency. They also report that some teams have strict language requirements for coding rounds, so confirm your team's language and focus with your recruiter before you start preparing.

The Zscaler interview process

Zscaler candidates report 5 rounds · ≈ 4-6 weeks. The stages below are what candidates describe, not a published process.

Resume Screening

Source notes describe this stage only as a first review of your resume against the role's qualifications. The listed must-haves are strong proficiency in one core language (Java, C/C++, Python, Go, or JavaScript/TypeScript for frontend roles), plus computer networks, operating systems, and data structures and algorithms. Cloud platforms, Docker and Kubernetes, Temporal, and a background in security or cryptography are listed as nice-to-haves. Later rounds reportedly probe networking and OS internals, so you may be asked to explain any networking or systems claim on your resume in depth. Keep only what you can explain at the protocol or kernel level.

What to demonstrate

  • Whether your resume shows at least one of the core languages at working depth, and which one, since some teams reportedly have strict language requirements
  • Whether networking or operating-systems experience is stated concretely enough to match the must-have list

How to prepare

  • Rewrite networking and systems bullets to name the protocol, component or mechanism you worked on, such as a proxy, a TLS path or a thread pool, rather than only the product feature
  • Ask the recruiter which team and language the role uses, and whether the Talent Acquisition team shares preparation material before the technical rounds

Online Assessment

Source notes describe an online assessment on HackerRank or HackerEarth. It mixes multiple-choice questions on CS fundamentals with several coding problems on topics such as dynamic programming, trees and graphs, and the notes say this screen is common for campus and entry-to-mid-level applicants. The two halves need different preparation. The multiple-choice part needs fast recall of OS, DBMS and networking facts. The coding problems need careful, test-first work, because the prompt's examples and input bounds are the whole specification and an automated grader cannot hear what you meant.

What to demonstrate

  • Recall of CS fundamentals across operating systems, database systems and computer networks in multiple-choice form
  • Whether coding solutions to DP, tree and graph problems hold up on hidden cases, including empty, single-element and boundary inputs
  • Whether the chosen algorithm fits the input bounds stated in the prompt

How to prepare

  • Build a short recall sheet covering deadlock conditions, paging and the TLB, ACID and isolation levels, TCP vs UDP, the OSI layers, and IPv4 vs IPv6 header differences
  • Before submitting each problem, run the worked examples plus an empty and a single-element input through a small harness you wrote first
  • Practise DP, tree and graph problems in a HackerRank-style editor, reading the constraints before choosing an approach

Technical Interview Rounds

Source notes describe two to three technical rounds with real-time coding in collaborative editors, system design, and deep-dive questions on networking and operating systems. Reported questions by category include, for coding, an LRU cache or min stack, BST two-sum, matrix shortest path, topological sort and longest common substring; for networking, TCP vs UDP, TLS handshakes and proxy interception, L4 vs L7, and IPv4 vs IPv6; and for systems, virtual memory, deadlock, and mutexes and semaphores. Source notes say some interviewers may follow a structured sheet of theory questions and listen for specific terms. Some candidates also report interviewers who interrupt during coding or keep cameras off. Precise vocabulary and a plan stated aloud before you code help in both situations.

What to demonstrate

  • Whether you can write correct, efficient code live and explain its time and space complexity
  • Whether you explain protocol behaviour mechanically, for example what each TLS message does or how MSS is derived from MTU, rather than by definition
  • Whether OS and concurrency answers hold up under follow-up, from the deadlock conditions to a working synchronised queue
  • Whether a design discussion covers the data model, scaling and failure handling

How to prepare

  • Clarify inputs and edge cases and state your approach and its complexity before you type, then narrate while coding so an interviewer who interrupts can follow
  • Rehearse the URL-to-page and TLS-interception walkthroughs aloud until you can give them without notes and with correct terminology
  • Write a bounded producer-consumer queue and an LRU cache from a blank editor in your team's language

Techno-Managerial Round

Source notes describe this as a final technical discussion with a manager or director on advanced topics. They also place scenario and leadership questions in the techno-managerial and managerial conversations: real-world challenges, teamwork and career growth. Expect to move between depth on architecture you have built and questions about how you work. Reported prompts in the behavioural category include solving a complex technical issue under a tight deadline, and balancing individual contributor work with mentoring junior engineers or joining architecture discussions.

What to demonstrate

  • Depth on systems you have built: why the architecture looks the way it does and what you would change
  • How you handled a hard technical problem under a deadline, including the trade-offs you accepted
  • How you balance your own delivery against mentoring and design work

How to prepare

  • Prepare one project at three depths: a short summary, a version of a few minutes, and a full design-review walkthrough
  • For each major design decision in that project, write down the alternative you rejected and why
  • Prepare a mentoring story with a real conflict between your own deadline and a junior engineer's needs, and say what you prioritised

Behavioral HR Round

Source notes describe the final round as a discussion with an HR representative about cultural fit and compensation. Reported prompts in the behavioural category include why you are leaving your current role, what attracts you to Zscaler's scale and architecture, and how you handled a difficult stakeholder or team member. Keep your answers specific and honest. The source notes advise acknowledging mistakes from past projects and saying so plainly when you do not know something.

What to demonstrate

  • Whether your reasons for leaving and for choosing this role are consistent and specific
  • How you resolved a conflict with a stakeholder or teammate, and what you did yourself
  • Whether your compensation expectations and constraints are stated clearly

How to prepare

  • Write a why-Zscaler answer that names the work you want to do, such as proxy, data-plane, control-plane or frontend engineering, rather than repeating marketing figures
  • Set a compensation range from your own data points for the level and location before the call, and state it plainly
  • Prepare a conflict story that ends with what changed in how you work, not only with how the disagreement ended

Where candidates lose points

Describing TLS interception as 'the proxy decrypts the traffic' without the two sessions and the trust anchor

A reported networking question pairs the TLS handshake with how a proxy intercepts it, so a one-line answer invites follow-ups. Describe two independent TLS sessions. The proxy ends the client's session with a certificate for the requested hostname, signed by an enterprise root CA the client already trusts. It then opens its own session to the origin, and it must validate the origin's certificate itself. Name the limits too: clients that pin certificates break, and anything the proxy fails to validate upstream becomes the client's blind spot. Use exact terms (SNI, key share, CertificateVerify, Finished), because source notes say some interviewers may work from a question sheet and listen for specific terminology.

Walking the URL-to-page path as 'DNS, then TCP, then HTTP' and skipping the MSS/MTU and DNS detail the question asks for

The reported version of this question explicitly asks for TCP MSS/MTU and DNS resolution detail. MSS is announced in the SYN and equals the MTU minus the IP and TCP headers: 1460 bytes on a 1500-byte MTU with IPv4 and no options. Path MTU discovery relies on ICMP, so blocked ICMP produces a connection that completes the handshake and then stalls on full-size segments. Tunnels usually fix this with MSS clamping. For DNS, separate the stub resolver, the recursive resolver and the authoritative servers, and say where caching and TTLs apply.

Preparing for the online assessment as if it were coding only

Source notes describe the HackerRank or HackerEarth assessment as a mix of multiple-choice CS fundamentals and coding problems on dynamic programming, trees and graphs. Revise OS, DBMS and networking facts as short recall items. For the coding part, test your solution against the prompt's examples plus empty and single-element inputs before submitting, because an automated grader gives you no chance to explain what you meant.

Reciting the four deadlock conditions or mutex vs semaphore without being able to write working synchronisation

Systems questions in the source notes run from deadlock and semaphores to a thread-safe producer-consumer queue, and the bank includes a multithreading coding item. Be ready to write the bounded queue: one mutex, a not-full and a not-empty condition variable, and waits inside while loops so a spurious wakeup rechecks the predicate. Then show deadlock prevention in code by acquiring locks in one global order, which breaks the circular-wait condition.

Coding in a language the team does not accept, or preparing for the wrong language track

Source notes report that some backend teams may require Java, C++ or Go, while automation teams may focus on Python. The reported fundamentals questions also split by track: smart pointers and memory leaks for C++ roles; the Java memory model, garbage collection and Spring transactions for Java roles. Ask your recruiter which language and track apply before you start preparing, then practise in that language with autocomplete turned off.

Questions & practice

Given a binary search tree (BST), describe and implement multiple approaches to find if there are two elements that sum up to a target value K.

Medium · data structures and algorithms

Approach

  1. Walk one small example through your approach before writing the whole thing.
  2. State the target complexity and say which constraint rules the naive version out.
  3. Choose the data structure from the access pattern, not from familiarity.

Follow-up

  • What is the worst case, and how likely is it on real data?
  • Which test case would catch an off-by-one here?

Implement a custom Least Recently Used (LRU) Cache or a stack that supports retrieving the minimum element in O(1) time.

Medium · data structures and algorithms

Approach

  1. State the target complexity and say which constraint rules the naive version out.
  2. Name the brute-force solution and its complexity before improving on it.
  3. Walk one small example through your approach before writing the whole thing.

Follow-up

  • Which test case would catch an off-by-one here?
  • What is the worst case, and how likely is it on real data?

Given a 2D matrix, find the shortest path from the top-left to the bottom-right corner using dynamic programming or graph traversal.

Medium · data structures and algorithms

Approach

  1. Name the brute-force solution and its complexity before improving on it.
  2. Choose the data structure from the access pattern, not from familiarity.
  3. Restate the input: its shape, its size, and what is guaranteed about it.

Follow-up

  • Which test case would catch an off-by-one here?
  • How does this change if the input no longer fits in memory?

Solve a classic graph problem involving cycle detection or topological sorting to manage dependencies in a distributed system.

Medium · data structures and algorithms

Approach

  1. State the target complexity and say which constraint rules the naive version out.
  2. Choose the data structure from the access pattern, not from familiarity.
  3. Name the brute-force solution and its complexity before improving on it.

Follow-up

  • How does this change if the input no longer fits in memory?
  • What is the worst case, and how likely is it on real data?

Explain the concept of virtual memory and how the operating system maps it to physical memory closest to the CPU.

Medium · languages, concurrency and fundamentals

Approach

  1. Reach for the cheapest primitive that closes the race, not the broadest lock.
  2. Distinguish a value from a reference to it, and say which one you handed out.
  3. Identify the window where an invariant is briefly untrue.

Follow-up

  • How would you prove the race exists rather than suspect it?
  • Where could this allocate more than you expect?

For C++ roles: Explain the differences between raw pointers, unique pointers, and shared pointers, and write a code snippet demonstrating how to avoid memory leaks.

Medium · languages, concurrency and fundamentals

Approach

  1. Identify the window where an invariant is briefly untrue.
  2. Distinguish a value from a reference to it, and say which one you handed out.
  3. Name what is shared across threads and what owns each piece of state.

Follow-up

  • What happens if two callers reach this at the same time?
  • How would you prove the race exists rather than suspect it?

Find peak concurrent sandbox usage from run intervals

Medium · sweep-line · intervals · concurrency-caps · null-semantics

Given up to 5 million job_run rows for one tenant over one day, with run_id, started_at, finished_at, status and wall_clock_limit_seconds, report the maximum number of sandboxes running at once, the earliest instant that maximum is reached, and the first run_id that would breach a per-tenant cap of C. started_at is null while a run is queued; finished_at is null both for runs still executing and for runs in status lost. Treat a run as occupying [started_at, finished_at). Give the complexity and state how you handle each null.

Approach

  1. Turn each run into two sweep events, (started_at, +1) and (end, -1), then sort the 2n events by timestamp with -1 ordered before +1 at equal timestamps. That tie-break is what makes the interval half-open, so a run finishing at 10:00:00 and one starting at 10:00:00 never overlap.
  2. Decide each null out loud before sweeping, because each choice moves the answer. A null started_at means queued and contributes nothing. A null finished_at with status running or leased is clipped to the window end. Status lost has no observed end at all, so clip it at started_at + wall_clock_limit_seconds on the grounds that the supervisor owns the timeout, and record that you did. The table's check (finished_at is null or started_at is not null) guarantees you never see an end without a start.
  3. Sweep once, maintaining a running counter, the maximum, and the timestamp at which the maximum was first attained (update peak_at only on a strict increase, or you will report the last such instant instead of the earliest). Capture the first run_id whose +1 takes the counter to C+1 during the same sweep rather than in a second pass.
  4. Complexity: O(n log n) dominated by the sort, O(n) space. If rows already arrive ordered by started_at, a min-heap of end times gives O(n log k) time and O(k) space with k the peak concurrency, which is the better shape when the rows come from an index scan on (tenant_id, started_at).
  5. If second resolution is acceptable, counting-sort the endpoints into an 86,400-slot delta array and prefix-sum it: O(n + T) time and O(T) space, which beats the comparison sort at 5 million rows. It answers only at second granularity, so state which resolution the cap is defined in.

Worked solution (20 min)

  1. Write the null policy as three lines of prose first, one per case, and keep them beside the output.
  2. Emit 2n endpoint tuples (timestamp, delta, run_id) and sort on the key (timestamp, delta) so -1 precedes +1.
  3. Sweep, tracking cur, peak, peak_at updated only on a strict increase, and the first run_id whose +1 takes cur to C+1.
  4. Build a fixture with two runs where one ends exactly when the next starts, three genuinely overlapping runs, one run with a null finished_at and status running, and one with status lost and a 300-second wall_clock_limit_seconds.
  5. Re-run with every timestamp shifted by a constant and confirm the peak is unchanged while peak_at shifts by the same constant.

Expected result: Peak is 3, from the overlapping trio. The exact-handoff pair yields a peak of 1, not 2. peak_at is the start instant of the third overlapping run. The lost run occupies exactly [started_at, started_at + 300s) under the stated policy.

Verify it yourself

  • Setting peak_at on >= rather than > moves the reported instant to the last time the peak was attained. Flip it and watch the fixture change.
  • Sorting by timestamp alone, without the delta tie-break, raises the reported peak on the handoff fixture.
  • The deltas over the whole sweep sum to zero once every open-ended run has been clipped.

Follow-up

  • Now report peak concurrency per tenant for 10,000 tenants from one globally sorted stream. What changes about memory and about the sort?
  • The cap has to be enforced at dispatch rather than reported afterwards. What does the admission check look like, and where does it race?
  • How would you answer 'peak concurrency within any 5-minute window' without re-sorting?

Explain why the metering dashboard scans every daily partition

Medium · indexing · partition pruning · sargability · tenant skew

usage_event is range-partitioned daily on ingested_at and holds tenant_id, workspace_id, environment, sku, quantity numeric(20,6), occurred_at and ingested_at. The only relevant index is on (occurred_at). A dashboard runs select sku, sum(quantity) from usage_event where tenant_id = $1 and date_trunc('hour', occurred_at) >= $2 and environment = 'production' group by sku, and EXPLAIN shows a sequential scan of every partition. Give each distinct reason, rewrite the predicate so an index can serve it, propose the index, and state the write cost its column order adds.

Approach

  1. Separate the three causes rather than blaming one. First, date_trunc('hour', occurred_at) wraps the column, so the predicate is not sargable against a btree on the bare column. Second, pruning keys off ingested_at while the query constrains occurred_at, so no partition can be excluded. Third, even made sargable, (occurred_at) is not tenant-leading, so for one tenant among thousands the scan reads the whole time range and discards nearly all of it.
  2. Rewrite the bound carefully, because the obvious rewrite is only conditionally equivalent. date_trunc('hour', x) >= $2 equals x >= $2 only when $2 is already hour-aligned; for an arbitrary $2 it means x >= date_trunc('hour', $2) + interval '1 hour'. Normalise the parameter in the caller and leave the column bare.
  3. Restore pruning with a second, redundant predicate on the partition key: ingested_at >= $2 - interval '<late-data horizon>'. State both sides of it. It prunes to a handful of partitions, and it silently omits any event whose ingest lagged past that horizon, which is precisely what a producer replay produces. Either document the horizon as a stated bound, or partition on occurred_at and move the problem into the dedup window instead.
  4. Propose (tenant_id, occurred_at) include (sku, quantity) per partition. A partial index where environment = 'production' mostly saves size rather than selectivity, since production dominates the three environments; take it if non-production is a meaningful share and skip it otherwise.
  5. Price the write path honestly. At roughly 250M rows/day each extra index is another insert plus WAL per row, and a tenant-leading key scatters inserts across one hot leaf per active tenant instead of appending to a single rightmost leaf, so page dirtying and random I/O both rise. An INCLUDE payload widens every leaf entry and enlarges the index accordingly.
  6. Add the index-only-scan caveat before someone reports it as a regression: on a freshly appended table the visibility map is not yet set for recent pages, so the INCLUDE columns still cost heap fetches until autovacuum has been through, and the newest hour is exactly the data the dashboard reads.

Follow-up

  • CREATE INDEX CONCURRENTLY is not supported on a partitioned parent. Give the sequence that gets this index onto 400 existing partitions without blocking ingest.
  • One tenant holds 200 times the median row count and the dashboard still times out for them with the index in place. What changes?
  • Should this read hit usage_rollup_hourly instead? State what that costs in freshness and what the watermark lets you promise.

Migrate a live partitioned event table without blocking ingest

Hard · online migration · ddl locks · expand and contract · partitioning

usage_event is range-partitioned daily on ingested_at, holds roughly 250M rows per day across 400 live partitions, and is written at 10-40k rows/second. Two changes are required: quantity must move from double precision to numeric(20,6), and a new environment column must become NOT NULL with a default of 'production'. Ingest cannot stop. Give the ordered plan, naming for each step the lock it takes, what that lock blocks, and roughly how long it is held. Identify the one step that cannot be rolled back cleanly once traffic depends on it.

Approach

  1. Classify the two changes before planning anything. Adding a column with a non-volatile default has been metadata-only since PostgreSQL 11, so it is cheap. Changing double precision to numeric is not binary-coercible, so alter column ... type rewrites every partition under ACCESS EXCLUSIVE and rebuilds its indexes; on this volume that is hours of blocked ingest and is simply not an option, which is why the plan is expand-and-contract rather than one statement.
  2. Expand: add quantity_numeric numeric(20,6) and environment with its default on the parent. Both are catalogue-only but both take a brief ACCESS EXCLUSIVE that cascades to partitions, so run each with lock_timeout set to a second or two and retry on failure. A queued ACCESS EXCLUSIVE request blocks every reader behind it, which is how a metadata-only change turns into an outage.
  3. Dual-write: deploy producer code that populates both columns on every insert, and leave it running before anything reads the new column. This is the step that cannot be reverted cleanly. Once readers depend on quantity_numeric, reverting the writer leaves rows with a null there, and the gap is only discoverable by re-reading the old column, which the readers have stopped doing.
  4. Backfill older partitions in batches keyed on the primary key, oldest first, committing every few thousand rows with a pause between batches, and skipping the partition still receiving writes until it rotates. Each batch is an ordinary UPDATE taking row locks only. The cost is bloat and WAL rather than blocking, so watch dead tuples and let autovacuum keep pace instead of wrapping 400 partitions in one transaction.
  5. Make NOT NULL cheap with the three-step form: add constraint ... check (environment is not null) not valid (brief ACCESS EXCLUSIVE, no scan), then validate constraint (SHARE UPDATE EXCLUSIVE, scans while reads and writes continue), then set not null, which from PostgreSQL 12 uses the validated check and skips its own full scan. Do this per partition, then on the parent.
  6. Switch and contract: move reads to the new column behind a flag, verify over a full period that both columns agree on freshly written rows, drop the old column (metadata-only), and only then remove the dual-write. Any index on the new column goes on with CREATE INDEX CONCURRENTLY per partition, since CIC is not supported on a partitioned parent: create the parent index with ONLY, build each child concurrently, then ALTER INDEX ... ATTACH PARTITION until the parent index becomes valid.

Worked solution (45 min)

  1. On a scratch cluster, build 10 partitions of 2M rows each and run a writer at a few thousand inserts/second.
  2. Run the naive type change and measure how long writes stall and how far ingest lag grows before killing it.
  3. Run the expand step with lock_timeout = '2s' while the writer runs, and observe a clean lock timeout and retry instead of a pile-up of blocked readers.
  4. Backfill in 5k-row batches and chart dead tuples and WAL generated per batch.
  5. Run the not-valid, validate, set-not-null sequence and confirm from pg_stat_activity and timings that nothing held an exclusive lock through a full scan.
  6. Add an index with CIC per partition plus ATTACH PARTITION and confirm the parent index reports valid only after the last attach.

Expected result: An ordered expand, dual-write, backfill, switch, contract plan with the lock named per step: metadata-only ADD COLUMN under a brief ACCESS EXCLUSIVE taken with lock_timeout; batched UPDATE backfill under row locks; CHECK NOT VALID, then VALIDATE under SHARE UPDATE EXCLUSIVE, then SET NOT NULL; CREATE INDEX CONCURRENTLY per partition with ATTACH PARTITION; and the dual-write-to-read switch identified as the step that cannot be reverted cleanly.

Verify it yourself

  • No step in the plan holds ACCESS EXCLUSIVE for longer than the configured lock_timeout.
  • The writer's error rate stays at zero through the rehearsal apart from the deliberate lock timeout.
  • After VALIDATE, SET NOT NULL completes in milliseconds on a table where the naive form scanned every row.
  • Freshly written rows agree on both columns for a full verification period before the old column is dropped.

Follow-up

  • A CREATE INDEX CONCURRENTLY fails halfway through the partition list. What state is the table in, how do you detect it, and what do you run?
  • The producer computes quantity itself. What happens to a request already in flight when the dual-write deploy lands, and does it matter?
  • Give two queries that prove the backfill is complete: one cheap enough to run every minute, one authoritative.

How does an SSL/TLS handshake work, and how does a proxy device intercept and secure this traffic?

Medium

Approach

  1. Work from the requirement backwards to the design.
  2. Say what you would check first and why it is the highest-information step.
  3. Clarify what is being asked and what a complete answer contains.

Follow-up

  • What assumption would you test first?
  • How would you know your answer was wrong?

Specify webhook signature verification a customer can implement

Easy · webhooks · hmac · replay protection

The webhook-delivery service signs each payload before POSTing it to a customer endpoint. Write the signature specification a customer implements in their own language: the header format, exactly which bytes are signed, the algorithm, how replay is bounded, and how a signing secret rotates without a delivery gap. Then write the verification steps the customer performs, in order, including what they compare and what they return on failure. Constraint: most customers reach for their web framework's parsed JSON body by default. Deliverable: the spec section plus reference pseudocode.

Approach

  1. Sign the concatenation of the timestamp and the raw body, t + "." + body, and emit a header of the form t=<unix seconds>,v1=<hex>. The timestamp has to be inside the MAC, or an attacker re-stamps a captured body and the tolerance window buys nothing.
  2. Require the raw request bytes. A framework that parses JSON and re-serialises it changes key order, whitespace and number formatting, so the spec must tell the customer to capture the body before the parser runs and give the middleware note for each common framework.
  3. Use HMAC-SHA256, not sha256(secret || body): SHA-256 is a Merkle-Damgard construction, so the naive form admits length extension. Require a constant-time comparison as well, since a short-circuiting byte compare leaks the expected prefix under repeated probing.
  4. Bound replay in two layers: reject when |now - t| exceeds a stated tolerance such as 300 seconds, then deduplicate on the event identifier header. The tolerance is what makes the customer's dedup store finite rather than unbounded.
  5. Rotate by allowing two live secrets and emitting both signatures in one header (v1=<old>,v1=<new>); the customer accepts if any candidate matches, so neither side needs an instantaneous cutover. A failed verification returns 400 and the body is not processed.

Worked solution (15 min)

  1. Write the header grammar and one real example line with a plausible timestamp and hex digest.
  2. Write the signed string construction explicitly as a byte concatenation, and add the sentence telling the customer where in their framework to obtain the raw body.
  3. Write the five verification steps in order: extract t and candidates, check the tolerance, recompute the HMAC over t + '.' + raw body, compare in constant time against each candidate, then deduplicate on the event identifier.
  4. Add the rotation paragraph: two active secrets, both signatures sent, overlap window stated in the dashboard.
  5. State the failure response and the fact that the payload is not processed, plus what the sender does with that 400.

Expected result: A spec where the signed input is the timestamp joined to the exact raw bytes, the algorithm is HMAC-SHA256 compared in constant time, replay is bounded by a stated tolerance plus event-id deduplication, and rotation is an overlap of two accepted signatures rather than a cutover.

Verify it yourself

  • The timestamp is inside the signed string, not merely sent alongside it.
  • The spec names raw bytes and says where the customer gets them before parsing.
  • Rotation requires no coordinated instant on either side.
  • The reason for HMAC over sha256(secret || body) is stated as length extension, not as a preference.

Follow-up

  • A customer's verification passes locally and fails in production behind a proxy that re-encodes the response body. Where do you look first?
  • Why sign with a per-endpoint secret rather than the tenant's API key?

Invoice detail latency triples after an ORM relationship refactor

Easy · n+1 query · orm · latency regression

An invoice detail endpoint returned in 40 ms at p99 last week. After a refactor replaced a hand-written join with ORM relationship access it returns in 1.4 s, and the regression grows with the number of invoice_line_item rows on the invoice. Database CPU rose, but no statement in the slow-query log exceeds 3 ms. You have request traces with per-span SQL, the ORM statement log, and a staging copy of the data. Produce an ordered diagnostic checklist, the measurement that confirms the cause before any code change, and the fix.

Approach

  1. Count statements per request before reading any statement duration. A slow-query log hides this class by construction, because every individual query is fast and only their number is wrong; take one trace and count SQL spans.
  2. Establish proportionality rather than asserting it: sample invoices with 5, 20, 60 and 200 line items and plot statements per request against line count. A straight line of slope 1 through an intercept of one or two identifies a lazy relationship load, and no index or cache would move that line.
  3. Locate the emitting attribute access in the refactored code and check whether the same shape repeats one level deeper, for instance a tax or adjustment collection hanging off each line, which turns the cost quadratic.
  4. Fix with a bounded statement count: either one join that fetches invoice and lines together, or two statements where the second is WHERE invoice_id = $1 AND tenant_id = $2. Keep tenant_id in the predicate so the read stays tenant-scoped even though invoice_id already implies it.
  5. Choose between the two deliberately: the join duplicates the wide parent row across N children on the wire, the two-statement form avoids that for one extra round trip. Prefer the join for narrow parents and the split for wide ones.
  6. Pin it with a per-request statement-count assertion in a test that varies line count, because a latency assertion passes on a small fixture and would not have caught this.

Follow-up

  • The endpoint now also needs per-line tax rows. Show the shape that keeps statement count constant instead of reintroducing the same defect one level down.
  • How does this change if a transaction-pooling proxy sits between the service and the database, so each statement may land on a different backend session?
  • The same page paginates invoices with LIMIT and OFFSET. Why is that a second, independent defect, and what replaces it?

Suggested practice checklist

Day one measures instead of guessing, under a fixed rubric, and the remaining hours are allocated in proportion to the gaps before any studying begins. The allocation is deliberately not renegotiated midweek, because the area that feels worst on day three is usually the one that is moving.

Day 1 — Networking path: from URL to first byte

  • Write the URL-to-page walkthrough end to end: DNS resolution (stub resolver, recursive resolver, caching and TTL), the TCP three-way handshake, the TLS handshake, then the HTTP request. At each step, name the layer and the header fields involved.
  • Add the MSS/MTU detail the reported question asks for: how MSS is derived from MTU, how path MTU discovery depends on ICMP, and why filtered ICMP causes connections that stall on large transfers.
  • Answer TCP vs UDP and L4 vs L7 as choices with reasons: what each gives up, and what a device can decide when it sees only addresses and ports versus the full HTTP request.
  • Practise the bank networking items Application Layer Protocols and IPv4 vs IPv6 and OSI.

Deliverable: A one-page layered diagram of a page load that you can redraw from memory, with the MSS/MTU and DNS steps annotated.

Day 2 — TLS interception and packet-level debugging

  • Walk through the TLS 1.3 handshake (ClientHello with key share and SNI, ServerHello, encrypted certificate and CertificateVerify, Finished) and say where TLS 1.2 needs an extra round trip.
  • Explain proxy interception as two TLS sessions. The proxy presents a certificate for the requested host, signed by an enterprise root CA the client trusts, and opens its own validated session to the origin. Name what breaks it, such as certificate pinning.
  • Compare IPv4 and IPv6 headers: IPv6 has a fixed 40-byte header, no header checksum, no fragmentation by routers, extension headers and a flow label. If asked about collision avoidance, note that CSMA/CA is a link-layer mechanism before you answer.
  • Diagnose a slow connection layer by layer with dig, traceroute and a packet capture, using the bank items TCP, DNS, Traceroute, and Wireshark and Networking, DNS, TLS, and PCAP.

Deliverable: A written triage order for DNS, TCP and TLS latency, and a two-session diagram of TLS interception.

Day 3 — Coding core: pointers, stacks and caches

  • Solve Delete Odd Nodes in Linked List in place, drawing the pointer rewiring for lists of length 0, 1, 2 and 3 before you run the code.
  • Implement Min Stack in O(1) with an auxiliary stack of minimums. Push onto it when the new value is less than or equal to the current minimum, so duplicate minimums survive a pop.
  • Implement the LRU cache as a hash map into a doubly linked list with sentinel head and tail nodes, and test the eviction order after a get refreshes a key.
  • Solve BST two-sum three ways: in-order into an array plus two pointers (O(n) time, O(n) space), a hash set during traversal, and forward and reverse in-order iterators (O(n) time, O(h) space). Check that the two values come from different nodes.
  • Do one set of multiple-choice practice on OS, DBMS and networking fundamentals, since the online assessment is described as mixing these with coding.

Deliverable: Four working solutions, each with its complexity stated and a list of edge-case tests.

Day 4 — Graphs and dynamic programming

  • Matrix shortest path: use DP only when moves are restricted to right and down. With four-way movement and obstacles, use BFS for unit cost or Dijkstra for non-negative weights. Say which case the prompt's rules create before you code.
  • Cycle detection and topological sort: Kahn's algorithm with a min-heap gives the lexicographically smallest order, and emitting fewer than V nodes means there is a cycle. Practise the bank item Cycle Detection or Topological Sort.
  • Longest common substring: dp[i][j] is the length of the common suffix ending at i and j, reset to 0 on a mismatch. It runs in O(mn) time and O(min(m, n)) space with a rolling row.
  • Work the reviewed exercise Find peak concurrent sandbox usage from run intervals to practise sweep-line tie-breaks and handling of nulls.

Deliverable: Three graph or DP solutions plus the sweep-line exercise, each with the input bound that justifies its complexity.

Day 5 — Operating systems, concurrency and language internals

  • Explain virtual memory: page tables, the TLB, page faults, and what a context switch costs in cache and TLB state.
  • Name the four deadlock conditions (mutual exclusion, hold and wait, no preemption, circular wait) and show prevention by breaking one of them, usually with a global lock order.
  • Write a bounded producer-consumer queue with a mutex and two condition variables, waiting inside while loops, and contrast a mutex (ownership) with a counting semaphore (permits). This covers the bank item Multithreading and Producer-Consumer Coding.
  • Language track. For C++: raw vs unique_ptr vs shared_ptr, a leak fixed with RAII, and a shared_ptr cycle broken with weak_ptr. For Java: the memory model, garbage collection and Spring transactions (bank item Java Microservices Transaction Handling).

Deliverable: A producer-consumer implementation that passes a stress test, and a one-page note for your language track.

Day 6 — Design and data questions

  • Practise the bank design item Design Global Metrics Monitoring and Real-Time Alerting. State the requirements, data model and hot path, and how the design fails. For related bank practice, try Design a Multi-Dimensional Job Rate Limiter or TTL and Data Pipeline with Rate Limiting.
  • Work the reviewed exercises Specify webhook signature verification a customer can implement (HMAC, replay bounds, key rotation) and Migrate a live partitioned event table without blocking ingest (transactions and locks).
  • Attempt the bank items Insert-Only Query with Hidden Updates and Transactions in Data Systems, stating the isolation level your answer assumes.
  • Rehearse one past project at three depths so an interviewer can pull you to any level mid-answer.

Deliverable: One design write-up that includes its failure modes, and a project walkthrough you can deliver at three depths.

Day 7 — Behavioral and HR preparation, then a full mock

  • Prepare stories for the reported prompts: a complex technical issue under a tight deadline, a difficult stakeholder or teammate, balancing IC work with mentoring, and why you are leaving your current role.
  • Write a why-Zscaler answer tied to the work you would do (proxy, data plane, control plane or frontend), not to figures you cannot source.
  • Set a compensation range from your own data points for the level and location before the HR conversation.
  • Run a mock with a partner who interrupts and keeps their camera off, mixing one networking deep-dive, one coding problem and one behavioural prompt.
  • Confirm the coding language with your recruiter, and ask whether preparation materials are available for your panel.

Deliverable: Four rehearsed stories, a why-Zscaler answer, and notes from one interrupted mock.

Know where your numbers came from

Source notes place scenario and leadership questions in the techno-managerial and managerial conversations, which cover real-world problems, teamwork and career growth. They describe the final HR round as a conversation about cultural fit and compensation. Tell each story from the decision point: the constraint you faced, the options, what you chose and what you would change. Have a candid account of a mistake ready. Answer 'why Zscaler' with the work you want to do there rather than with figures you cannot source.

  1. Tell me about a time you had to solve a highly complex technical issue under tight deadlines. What was your approach?
  2. Why are you looking to leave your current role, and what specifically attracts you to the scale and architecture of Zscaler?
  3. Walk through a past project, including a mistake you made in it and what you changed afterwards.

Describe a situation where you had to work with a difficult stakeholder or team member. How did you resolve the conflict?

Medium · behavioural and engineering judgement

Approach

  1. Name the disagreement and how you resolved it with evidence.
  2. Give the blast radius: what could have broken, and what you measured.
  3. Pick a story where you made the decision, not one where you watched it.

Follow-up

  • What did you decide not to do, and why?
  • What would you do differently if you ran that again?

How do you balance individual contributor (IC) tasks with mentoring junior engineers or participating in architectural discussions?

Medium · behavioural and engineering judgement

Approach

  1. Name the disagreement and how you resolved it with evidence.
  2. Pick a story where you made the decision, not one where you watched it.
  3. Give the blast radius: what could have broken, and what you measured.

Follow-up

  • What would you do differently if you ran that again?
  • What did you decide not to do, and why?

Reverse a webhook ordering decision after measuring its cost

Medium · reversing decisions · head-of-line blocking · at-least-once · api contracts

You argued for strict per-subscription ordering in webhook-delivery, which means one in-flight attempt per subscription. It shipped. Three months later a single unresponsive endpoint holds one subscription's queue at a six-hour backlog, and two customers report events arriving out of order anyway once their own retries are counted. Describe a decision you reversed: what you originally optimised for, the measurement that changed your mind, what the reversal cost in engineering time and customer change, and how you told the people who had already built on the original guarantee.

Approach

  1. State the original decision as a trade you made knowingly. Ordering across a network requires a single in-flight attempt per subscription, and its price is head-of-line blocking whenever one endpoint is slow. 'We priced it wrong' is a much stronger opening than 'we did not realise', and it is usually the true one.
  2. Bring the measurement that flipped it, not the anecdote: backlog age at the ninety-ninth percentile per subscription, the share of subscriptions where one slow endpoint gated an otherwise healthy queue, and the delivery throughput lost to serialisation. A reversal justified by complaints is indistinguishable from a reversal justified by fatigue.
  3. Name what you learned about the guarantee itself, which is the engineering content of this story. At-least-once delivery means a retried event already arrives after newer ones and the consumer already must be idempotent, so a guarantee the customer has to defend against anyway was never worth what it cost to provide.
  4. Describe the migration, because reversing a published contract is the hard half and the part candidates skip. Parallel attempts behind a per-subscription flag, a monotonically increasing sequence number added to the envelope so order-sensitive consumers can sort or discard, documentation that states at-least-once and unordered in those words, and a deprecation measured in quarters because the client is a pinned SDK inside a build pipeline you cannot see or redeploy.
  5. Give the cost in the two currencies that matter: engineer-weeks, and how many customers had to change code. Then say who you told before it shipped rather than in a changelog afterwards, and which large customer you left on the old behaviour and for how long.
  6. Close with the signal you now weight differently, stated as something you would do earlier next time: measuring the blocking cost on the slowest decile of endpoints before committing to the guarantee, rather than after a customer noticed.

Follow-up

  • A customer insists they need ordering. What do you offer them that is not global serialisation?
  • How did you choose the deprecation window given that you cannot see or redeploy the clients?
  • What would have to be true for you to reverse back?