Candidate reports place the Qualcomm Software Engineer role where hardware meets high-performance software. Most application roles hide the hardware. The work described here does the opposite: it sits directly on low-level architectures, mobile processors, neural processing units, GPU drivers, cellular modems and system-on-chip platforms. That code decides how memory is mapped, how processes are scheduled across cores and how power is managed.
The responsibilities in those reports include writing bare-metal code, Linux and Android kernel drivers, firmware for embedded processors and hardware acceleration libraries, and turning hardware specs and block diagrams into working C/C++ driver code. Bring-up work is described in both pre-silicon emulation and early post-silicon platforms. Performance and stability work covers latency, power profiles, deadlocks, memory leaks and memory corruption, with kernel tracing tools, trace analyzers and lab instruments.
For preparation, this means the interview material leans toward the machine rather than toward abstract puzzles. The reported questions ask why a struct is the size it is, what volatile stops a compiler from doing, what a mutex costs compared with a spinlock, how a virtual address becomes a physical one, and what happens between an interrupt firing and its handler running. The coding questions reported are linked lists, bit operations, array two-pointer work and a thread-safe ring buffer. A correct answer is only half the job. The other half is saying what your code does to memory, to the cache and to other threads.
The reports also say the emphasis changes by team. Specialized roles such as ASIC verification, multimedia drivers or ML infrastructure can replace generic data-structure problems with domain rounds on UVM/SystemVerilog, camera or computer-vision pipelines, or DSP algorithms. Ask your recruiter early which team you are interviewing for and which of these apply.
Recruiter Outreach
reportedCandidates describe this as a first recruiter contact about the opening and your interest in it. Use it to learn which team the role sits in and what the later rounds will focus on. Candidate reports say both depend heavily on the team (Modem, GPU, Linux Kernel, Multimedia, AI/NPU, Driver). The answers decide whether you spend the week on generic data structures or on a domain round.
What to demonstrate
- Whether your background (C/C++, kernel, firmware, embedded, drivers) matches the team the opening sits in
- Whether you can say in a sentence or two why low-level systems work is what you want to do
- Whether your constraints (start date, location, work authorisation) are clear before a loop gets scheduled
How to prepare
- Ask which team the role is on, which language the technical rounds expect, and whether a specialized domain round (verification, multimedia, DSP, ML infrastructure) is part of the loop
- Prepare a two-sentence summary of your most relevant low-level project: the hardware or OS layer it touched and the problem it solved
- Write your constraints down as one-line facts before the call so you state them rather than negotiate them on the spot
Initial Screening Phase
reportedCandidates describe this stage only as a preliminary check of basic qualifications and fit. Candidate reports also say initial technical screens are held virtually, so set up a quiet space and a plain editor you are comfortable writing C in. Treat this stage as the point where your resume starts to be tested: candidate reports say resume projects get probed in depth during the process, so anything you name here should be something you can explain down to the register or the lock.
What to demonstrate
- Whether your basic qualifications line up with the opening: the languages, operating systems and hardware layers you can speak to from real work
- Whether each resume project has a clear shape: the constraint, what you changed, how you measured the result
- Whether you can separate your own work from the team's on a shared project
How to prepare
- Before any screen, write one-paragraph answers to the reported fundamentals questions (endianness detection,
volatileandregister, dangling pointers, process versus thread) and say each aloud until it stays short and exact - For every project on your resume, list the three deepest follow-up questions someone could ask and make sure you can answer each one
- Attach a measured result to each project, or state plainly that it was never measured
Technical Deep Dives
reportedCandidates describe a series of technical interviews on deep domain knowledge. The reports stress follow-up questions that test how far your understanding goes past the first answer. Candidate reports give one example of such a follow-up: what happens if a spinlock is held inside an interrupt service routine. A memorised definition gets you through the first question. The follow-ups need the mechanism.
What to demonstrate
- Whether an OS or C answer holds up through two or three follow-ups: what the hardware, compiler or scheduler actually does
- Whether you can connect a concept to its failure mode, for example priority inversion to a stalled high-priority task, or cache thrashing to a loop's access pattern
- Whether you reason about memory layout, allocation and concurrency without being prompted
How to prepare
- For each reported OS topic (mutex, semaphore, spinlock, priority inversion, virtual memory, IPC), write the answer and then the next two follow-up questions with their answers
- Work through a spinlock shared between process context and an ISR: why process context must disable local interrupts while holding it, and why a sleeping lock cannot be taken in an ISR
- Trace a virtual-to-physical translation step by step: TLB lookup, page-table walk on a miss, page fault if the entry is not present
Full Loop Technical Interviews
reportedCandidates describe these as back-to-back technical interviews that need sustained energy. Candidate reports say many technical interviews have you write C on a whiteboard or in a plain editor without autocomplete, so hand-written pointer code, bit masks and loop bounds have to be right without a compiler to catch you. Use the reported coding questions (linked-list reversal, bit set/clear/flip, moving zeros while keeping order, a thread-safe ring buffer) as practice material for that kind of session, and prepare for the length of the day as well as the content.
What to demonstrate
- Whether hand-written C compiles in your head: correct pointer syntax, correct operator precedence, no off-by-one in array bounds
- Whether you state edge cases (empty input, single element, full and empty buffer, bit index out of range) before being asked
- Whether your explanation stays sharp in the later sessions of a back-to-back day
How to prepare
- Write the reported coding questions in C in a plain editor with no autocomplete, then compile them and count every error you would have shipped
- For the ring buffer, decide how you tell full from empty (leave one slot unused, or keep a count) and which synchronisation you use (a mutex plus condition variables for several producers, atomics only for the single-producer single-consumer case)
- Run at least one back-to-back mock of several technical sessions to find where your accuracy drops
Specialized Technical Rounds
reportedAccording to candidate reports, specialized roles such as ASIC verification, multimedia drivers or ML infrastructure can swap generic data-structure problems for domain interviews. Topics named include UVM/SystemVerilog, computer vision pipelines and DSP algorithms. Related bank topics include debugging a UVM verification environment, raw camera data processing, and AI/ML compiler concepts. If your recruiter confirms a domain round, prepare for it as a separate subject, not as an extension of the coding practice.
What to demonstrate
- Depth in the specific domain the team works in, rather than general algorithm fluency
- Whether you can debug a system in that domain step by step: isolate the failing stage, form a hypothesis, confirm it
- Whether you can explain the trade-offs particular to that domain (coverage closure, pipeline throughput, fixed-point precision) in plain terms
How to prepare
- Confirm with the recruiter which domain applies, and drop the others from your plan
- For verification roles, review UVM components versus UVM objects and describe how you would debug a failing test or close a coverage gap
- For multimedia or ML roles, walk through one pipeline you know end to end (raw sensor data to processed output, or model graph to compiled kernel) and name where it bottlenecks
2 candidate reports. Individual accounts describe a particular role and hiring cycle.
Qualcomm Software Engineer interview: friendly but unexpected technical scope
After the recruiter interaction, I had two technical interviews that mixed behavioral questions about my past experience with coding and other technical prompts. The interviewers were nice, which helped. Still, some questions went beyond the scope I thought had been set ahead of time. The coding was meant to probe how I reason under constraints, not random trivia, but the mismatch meant I had to…
Read full experienceQualcomm Software Engineer interview: 30-question screen and DSA threshold
My process began with a multiple-choice screen of 30 questions. I needed at least 50% correct to move on, so the threshold was clear from the start. The next step was a technical screen on algorithms and data structures. I worked through classic sorting-style material, including moving all zeros to the end of an array, along with other DSA questions based on common algorithm patterns. It felt str…
Read full experiencePracHub editorial advice for the preparation topics above.
Giving a textbook definition of a mutex, semaphore or spinlock and then stalling on the scenario follow-up
Candidate reports describe scenario follow-ups rather than definition checks, for example what happens if a spinlock is held inside an interrupt service routine. Prepare each primitive through its failure modes. A mutex may sleep, so it cannot be taken in interrupt context. A spinlock busy-waits, so it only suits short critical sections. If the same data is touched from an ISR, process context has to take the lock with local interrupts disabled, or the ISR can spin forever on that CPU. Priority inversion needs a low-priority holder, a high-priority waiter and a medium-priority task that preempts the holder.
Writing C that only works with a compiler and autocomplete to fix it
Candidate reports say many technical interviews use whiteboards or plain editors with no autocomplete. Practise the reported coding questions by hand and check them afterwards. Common slips: x & mask == 0 parses as x & (mask == 0), so parenthesise the mask. 1 << 31 on a signed int is undefined in C, so use 1u << n. Right-shifting a negative signed value is implementation-defined, so use unsigned types for register values. In linked-list reversal, save next before you overwrite the pointer.
Producing working code but not being able to say what it does in memory
Candidate reports say candidates who struggle often have working code but cannot explain memory layout, stack versus heap allocation, pointers or concurrency safety. After every solution, add a sentence on where each object lives, what gets copied, and what happens if two threads call the code at once. For struct questions, work the layout on paper. On x86-64, {char; int; double; short} is 24 bytes and shrinks to 16 when ordered largest-first. On 32-bit ABIs the result depends on whether double aligns to 4 or 8 bytes, so say which ABI you assume.
Listing resume projects you cannot defend at register, driver or lock level
Candidate reports say interviewers dig deep into resume projects: architecture choices, hardware tools used, bugs solved. Keep only projects you can explain three levels down. For each, prepare the hardest bug with its step-by-step isolation, one design decision with the alternative you rejected, and one measured result. Anything you cannot go deep on should become a single line, or come off the resume.
Treating `volatile` as a concurrency tool or skipping it on memory-mapped registers
Know exactly what volatile does. It stops the compiler from caching, merging or removing accesses, which memory-mapped registers and ISR-shared flags need. It does not make an operation atomic and it does not order memory between CPUs, so thread synchronisation still needs atomics, locks or barriers. When asked what happens on a register write, add that the store can be buffered or posted on the bus, which is why drivers read the register back or use a barrier before depending on the write having landed.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Solve array/string manipulation problems using two-pointer techniques …
Solve array/string manipulation problems using two-pointer techniques or sliding windows (e.g., Two Sum, reversing arrays, checking palindromes).
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Name the brute-force solution and its complexity before improving on it.
- Restate the input: its shape, its size, and what is guaranteed about it.
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?
Write a function to reverse a singly linked list in C/C++ in-place.
Write a function to reverse a singly linked list in C/C++ in-place.
Approach
- State the target complexity and say which constraint rules the naive version out.
- Name the brute-force solution and its complexity before improving on it.
- Restate the input: its shape, its size, and what is guaranteed about it.
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?
Write a program to set, clear, or flip specific bits (e.g., flip the 3…
Write a program to set, clear, or flip specific bits (e.g., flip the 3rd bit) in an integer using bitwise operations.
Approach
- Walk one small example through your approach before writing the whole thing.
- State the target complexity and say which constraint rules the naive version out.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement a thread-safe circular buffer (ring buffer) or FIFO queue wi…
Implement a thread-safe circular buffer (ring buffer) or FIFO queue with concurrent push/pop capability.
Approach
- State the target complexity and say which constraint rules the naive version out.
- Walk one small example through your approach before writing the whole thing.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- How does this change if the input no longer fits in memory?
- Which test case would catch an off-by-one here?
What is the difference between a Mutex and a Semaphore? When would you…
What is the difference between a Mutex and a Semaphore? When would you use a Spinlock over a Mutex?
Approach
- Reach for the cheapest primitive that closes the race, not the broadest lock.
- Say what the runtime actually does before reasoning about the code.
- Distinguish a value from a reference to it, and say which one you handed out.
Follow-up
- How would you prove the race exists rather than suspect it?
- Where could this allocate more than you expect?
Explain structure padding and packing. How do alignment requirements i…
Explain structure padding and packing. How do alignment requirements impact total structure size across 16-bit, 32-bit, and 64-bit architectures?
Approach
- Name what is shared across threads and what owns each piece of state.
- Distinguish a value from a reference to it, and say which one you handed out.
- Say what the runtime actually does before reasoning about the code.
Follow-up
- How would you prove the race exists rather than suspect it?
- Where could this allocate more than you expect?
Merge partitioned event streams into one ordered feed with bounded lateness
The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.
Approach
- Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
- Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
- Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
- Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.
- Choose the late-event policy from what the projection is keyed on. The projection upserts on (aggregate_id, aggregate_version) and discards a version it has already applied, so a late event is safe to apply out of order and correctness never depended on the merge at all. Apply it, recompute the affected feed page, and count lateness so the 30-second budget can be re-derived from data rather than folklore.
- Say what the merge does not buy: ordering is guaranteed within one aggregate by the log's partitioning, and no watermark makes the cross-aggregate order authoritative. Two events from different aggregates in the same millisecond have no true order, so the feed's order is a presentation choice that must be stable rather than correct.
Worked solution 35 min
- Write the heap comparator on (occurred_at, event_id) and the per-partition head refill.
- Write the watermark computation and the emit-loop condition, then list which buffered events are held at a chosen instant.
- Compute the buffer at 4,000 events per second, 30 seconds and 1 KB per event, and state what fraction of a worker's heap that represents.
- Add the idle-partition marker and trace the watermark with one silent partition, both with and without the marker.
- Write the late-event path and name the key that makes applying it safe.
Follow-up
- The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
- The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?
- One partition is ten minutes behind because its producer is slow. Do you stall the feed or emit without it?
Replace offset paging on the resource feed with keyset
resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.
Approach
- Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
- Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
- Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
- Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.
- State the residual honestly. Keyset is stable against concurrent inserts and deletes, but not against a row whose updated_at changes mid-scroll — that row moves in the ordering and can be seen twice. If the feed must be a snapshot, order by an immutable key or bound the page set with updated_at <= the cursor's start value.
- Keep a total out of the page path. A tenant-wide COUNT(*) is the scan keyset just removed; fetch LIMIT 51 and return has_more instead.
Worked solution 25 min
- Seed one tenant with 500k active resources, 2% of them sharing an identical updated_at.
- Time LIMIT 50 OFFSET 0 against OFFSET 20000 and record rows-read from EXPLAIN (ANALYZE, BUFFERS) for each.
- Page the whole set with the keyset query while an insert-only writer adds 100 rows/second, collecting resource_ids, and repeat the run with OFFSET.
- Repeat both runs under a second writer profile that also deletes 20 rows/second from pages already returned and bumps updated_at on 20 more, and diff each collected id set against the rows that existed for the whole run.
- Remove resource_id from the cursor so the seek degrades to updated_at < $2, and re-run the tie-heavy section of the feed.
Follow-up
- The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
- Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?
- What does the cursor do when the row it points at has since been deleted?
Keep soft-deleted accounts from blocking re-registration
app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.
Approach
- Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
- Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
- For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
- State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.
- Say what a soft delete must do besides setting deleted_at: increment auth_version so existing tokens stop validating, leave resource.owner_user_id and resource_revision.actor_user_id intact, and accept that the address is retained — erasure is a different requirement answered by scrubbing the column, not by a DELETE that would break those references.
Follow-up
- A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
- How do you honour an erasure request while resource_revision.actor_user_id still references this table?
- What changes if a user may hold membership in two tenants?
Explain the fundamental differences between bus protocols like AXI, AH…
Explain the fundamental differences between bus protocols like AXI, AHB, and standard interfaces like I2C vs. SPI.
Approach
- State the consistency you need, and where you are willing to be stale.
- Choose a partition key and say what query it makes expensive.
- Fix the scope first: who calls this, how often, and what they do when it fails.
Follow-up
- How does this behave when that dependency is down for an hour?
- What would you drop to keep the system up under load?
What happens internally when software writes to a memory-mapped regist…
What happens internally when software writes to a memory-mapped register in an embedded system?
Approach
- Choose a partition key and say what query it makes expensive.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
Follow-up
- How does this behave when that dependency is down for an hour?
- What would you drop to keep the system up under load?
Specify the outbound webhook contract a customer endpoint can verify
Egress delivery sends resource.created, resource.updated and resource.archived to roughly 40k customer endpoints at about 1.5k deliveries/second, with a per-destination concurrency cap of 4 and a 10 second connect-plus-read timeout, at-least-once from the relay. The receiver is code you do not control, often behind a proxy that may re-encode JSON. Specify the payload envelope, how the receiver verifies authenticity and rejects replays, what ordering it may assume, how it deduplicates, which status codes it should return and what each means to us, and the retry, circuit and replay behaviour.
Approach
- Send the fact, not a pointer: event_id, event_type, aggregate_type, aggregate_id, aggregate_version, occurred_at and the payload copied from outbox_event. A receiver told only that resource 42 changed has to call back, and the call back returns a newer state than the event describes - that is precisely how a consumer applies changes out of order while believing it is following them.
- Sign the exact bytes on the wire: HMAC-SHA256 over the timestamp, a separator, and the raw body, in a header, compared in constant time before the body is parsed. Instruct receivers to verify the raw bytes, never a re-serialised copy, since a proxy that reorders keys or changes whitespace invalidates a signature computed over re-encoded JSON. Reject a timestamp outside a tolerance - five minutes is typical - and keep a short seen-set of event_ids, because a capture replayed inside the tolerance still verifies.
- Support key rotation by sending several signature values in one header during the overlap window and publishing that any one that verifies is sufficient. Without that rule a key rotation is a synchronised outage across every destination at once.
- State the guarantee as it actually is: at-least-once and unordered, including within a single aggregate_id. The outbox is ordered per aggregate at the source, but the relay holds up to 4 requests in flight per destination and backs off each retry independently, so a version 6 delivery that needs one retry lands after a version 7 that succeeded on its first attempt. Publishing per-aggregate ordering we do not enforce is worse than publishing none, because a receiver that trusts it overwrites new state with old. Receivers deduplicate on event_id and apply conditionally - UPDATE ... WHERE aggregate_version < :incoming, or the same comparison under a row lock on the aggregate - which discards stale redeliveries and stays correct when two deliveries for one aggregate are processed at the same time. A duplicate and an out-of-order delivery then have the same outcome: no-op.
- Define the response contract in the receiver's terms. 2xx means durably accepted, and accepting means writing it down - a receiver that does its processing inline inside our 10 second timeout will be retried while it is still working. 4xx is permanent and we stop. 429, 5xx and timeouts are retried with capped exponential backoff and full jitter within the per-destination concurrency cap, and a circuit opens after a run of consecutive failures and half-opens on a schedule, so a permanently dead endpoint costs one probe per interval instead of a growing queue.
- Give them a recovery path that does not involve us holding a queue for everyone: a visible parked state, and a replay endpoint keyed by event_id or time range, so a receiver that was down for two hours asks for the gap on its own schedule.
Worked solution 30 min
- Write the envelope fields and mark which are needed for deduplication and which for discarding a stale delivery.
- Write the signature string construction and the receiver's verification steps in order, including the constant-time compare and the tolerance check.
- Write the receiver's idempotent apply: dedupe on event_id, then the version-conditional write that discards stale and concurrently delivered redeliveries.
- Write the status-to-action table from our side: which codes retry, which stop, and what opens the circuit.
- Describe the parked state and the replay call, including what the customer must supply.
Follow-up
- A customer insists an event never arrived. What do you check, in order, and which table settles the argument?
- A receiver cannot store a version and asks us to deliver their events in order. What would the relay have to give up to offer that, and what does one failing event then do to the rest of their stream?
Listing latency scales with page size, not with filters
The tenant listing endpoint reads resource filtered by tenant_id and status, ordered by updated_at DESC, and returns each row plus the owner's display name from app_user and the actor of that resource's latest resource_revision. p99 is 55 ms at 10 rows per page and 1.4 s at 200. Database telemetry shows 401 statements per request, each under 1 ms, and nothing in the slow-query log. Diagnose the cause and give the fix, stating the statement count per request and the p99 you expect afterwards.
Approach
- Read the counters before forming a theory. 401 statements for 200 rows is one driver query plus two per row, and sub-millisecond execution with an empty slow-query log rules out a bad plan. The time is round trips, which is why it is invisible in every per-query metric and scales with rows returned rather than with filter selectivity.
- Name the two per-row statements from their normalised text: a single-row app_user lookup by user_id, and a resource_revision lookup by resource_id ordered by version DESC LIMIT 1. Confirm by dropping those two response fields and watching the statement count fall to one. That locates the calls in the serialisation layer, not the repository.
- Check that the arithmetic accounts for the whole gap. Measure one round trip to the replica in isolation; 400 trips at roughly 3 ms of network plus 0.2 ms of execution is about 1.3 s on top of a 55 ms baseline, which matches. If the multiplication had fallen short, the N+1 would only be part of the story and you would keep looking.
- Batch both lookups. Collect owner_user_ids and resource_ids from the driver query, then issue WHERE tenant_id = $1 AND user_id = ANY($2) for the users, and PostgreSQL's SELECT DISTINCT ON (resource_id) ... WHERE resource_id = ANY($2) ORDER BY resource_id, version DESC for the latest revision, which the UNIQUE (resource_id, version) index serves directly. On an engine without DISTINCT ON, use a lateral join or a row_number window. Three statements per request at any page size.
- Keep the tenant predicate in the batched query. The per-row version was implicitly scoped because its ids came from tenant-scoped rows; a batched user_id = ANY(...) with no tenant_id is an unscoped read that behaves correctly only as long as the id list is trustworthy.
- Re-measure at 10, 50 and 200 rows and confirm the statement count is constant. Latency should now track bytes returned.
Follow-up
- The page size is capped at 200 today. What breaks first if it is raised to 2,000, and is it still this bug?
- How do you stop the next N+1 from reaching production, given that no individual query is slow and the endpoint's tests pass?
- The latest-revision actor is only used to render an avatar. Make the case for denormalising it onto resource, and name the write anomaly that introduces.
Day one measures instead of guessing, under a fixed rubric, and the remaining hours are allocated in proportion to the gaps before any studying begins. The allocation is deliberately not renegotiated midweek, because the area that feels worst on day three is usually the one that is moving.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01C memory layout and language details
- Answer the reported C questions in writing: endianness detection in C, structure padding and packing, `volatile` and `register`, the compile pipeline from source to binary, and dangling pointers
- Work struct sizes on paper for a mixed `char`/`int`/`double`/`short` struct under x86-64 and a 32-bit ABI, then reorder the members to minimise size and check with `sizeof`
- Write `memmove` by hand so it handles overlapping regions, and explain why `memcpy` does not have to
Deliverable: One page of C answers you can deliver from memory, plus a struct-layout worksheet checked against a compiler.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Bit manipulation and endianness coding
- Write set, clear, flip and test for bit n using unsigned masks, then write a byte-order swap for a 32-bit word with shifts and masks
- Count set bits two ways: a loop over all bits, then Kernighan's `x &= x - 1` at O(k) for k set bits, and explain why the second one terminates
- Solve the two-unique-numbers XOR problem and explain why isolating the lowest set bit splits the two numbers into different groups
Deliverable: A tested file of bit routines written first in a plain editor, with every hand-written mistake noted.
Practice prompt ↗Practice prompt ↗Practice prompt ↗03Pointer-based coding: linked lists and arrays
- Reverse a singly linked list in place in C with three pointers, and trace it on empty, single-node and two-node lists before running it
- Move all zeros to the end of an array while keeping the order of the other elements, in one pass with a write index
- Solve Two Sum with a hash map and a palindrome check with two pointers, stating the complexity of each before coding
Deliverable: Hand-written C solutions with edge-case traces written before compiling, and a count of the errors the compiler found.
Practice prompt ↗Practice prompt ↗04Operating systems and concurrency
- Write answers with follow-ups for process versus thread and context switching, mutex versus semaphore versus spinlock, priority inversion and inheritance, virtual memory translation, and IPC through shared memory
- Implement a thread-safe ring buffer with a mutex and two condition variables, and state how full and empty are told apart
- Solve producer-consumer with POSIX mutexes and condition variables, and explain why the wait sits inside a `while` loop and not an `if`
Deliverable: A working ring buffer that passes a multi-producer stress test, plus an OS answer sheet with two follow-ups per topic.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Computer architecture and the hardware-software interface
- Explain cache hits and misses, write-back versus write-through, coherence (MESI) and thrashing, then restructure a column-major loop over a row-major array and explain the locality gain
- Walk through a memory-mapped register write from the store instruction to the device, including why the access must be `volatile` and when a read-back or barrier is needed
- Explain the sequence from interrupt assertion to ISR execution, and compare AXI and AHB with I2C and SPI at the level of what each is for
Deliverable: A one-page diagram set: cache hierarchy, MMIO write path and interrupt flow, each explained aloud without notes.
Practice prompt ↗Practice prompt ↗06Debugging stories, resume depth and specialized topics
- Prepare the behavioral stories: the hardest bug from bring-up or emulation with step-by-step isolation, an optimisation for memory footprint or latency, and a technical disagreement with a hardware or verification team
- For each resume project, write the three deepest follow-up questions and answer them
- If the recruiter confirmed a specialized round, spend the remaining time on that domain (UVM, camera pipelines, DSP or ML compilers). Otherwise, walk through debugging driver-caused memory corruption step by step: the symptom, how you narrow it to the driver, the tools you would use, and how you confirm the fix
Deliverable: Three STAR stories with measured results, plus a follow-up sheet for every project on your resume.
Practice prompt ↗Practice prompt ↗07Back-to-back mock loop in a plain editor
- Run several technical sessions back to back with a partner: one C and memory, one bit or linked-list coding, one OS or concurrency, one architecture, all written without autocomplete
- Have the interviewer push every answer with at least two scenario follow-ups, such as a spinlock inside an ISR or an interrupt arriving mid-critical-section
- Note where accuracy dropped across the sessions and re-drill that topic briefly before the real loop
Deliverable: Mock scorecards for each session and a short list of the topics to review the night before.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The reported behavioral questions come from low-level engineering: a hard bug during bring-up or emulation, optimising for tight memory or latency, and disagreements with hardware or verification teams. Structure each answer with STAR, keep the focus on your own engineering contribution, and give the actual debugging steps and measurements, not a summary of the outcome.
How do you resolve technical disagreements with hardware or verificati…
How do you resolve technical disagreements with hardware or verification teams during project development?
Approach
- Close with what you would do differently, concretely.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What did you decide not to do, and why?
- How did you know your change caused the improvement?
Reverse your own decision and price the reversal
Describe a technical decision you made and later reversed. Pick one that cost something: a service you split and merged back, a cache you added and removed, an index you created that pushed the planner onto a worse plan, a projection you rebuilt from scratch. State what you believed when you decided, the measurement that changed your mind, how long the wrong version ran in production, and what the reversal cost in migrations, dual writes, and a deprecation window for callers you did not own.
Approach
- State the original rationale without irony, in the version you would still defend given what was known then. If it is not defensible, the story is about carelessness rather than judgement, and a different example serves you better.
- Give the measurement that moved with a before and after: the p99 that did not improve, the cache hit rate that sat at 40%, the plan that flipped to a sequential scan once the table passed a size you can name.
- Cost the reversal in steps, not adjectives: expand-and-contract deploys, the dual-write window, the callers who had to be notified, the rows already written in the wrong shape that had to be backfilled or abandoned.
- Distinguish reversal from rewrite by naming what you kept. Most good reversals preserve the schema or the interface and undo one decision inside it, which is also why they were affordable.
- Finish on the process change: the smallest experiment that would have produced the same measurement in a day, and why you did not run it the first time.
Follow-up
- What in that decision was irreversible, and did you know it was irreversible when you made it?
- How did you tell the people who had already built on top of the original decision?
- What do you now measure before committing to a change of this size?
Estimate work you have never done and defend the range
You are asked to estimate a change you have never attempted: add a column to a 100-million-row table, populate it, move reads across, and drop the old shape. Give a range with the assumptions that generate it, including batch size, the signal your backfill throttles on, and wall-clock hours, and name the three unknowns that would move the number most. Then describe a real estimate you gave under comparable ignorance: how you expressed its uncertainty, what you committed to, and how wrong you turned out to be.
Approach
- Decompose into independently deployable steps before estimating anything: add the column nullable, write both shapes, backfill in batches, verify, move reads, stop writing the old shape, drop it. That is four deploys spread over days, and the calendar estimate is dominated by them rather than by the loop's runtime.
- Do the arithmetic aloud for the part that has arithmetic in it: batch size times number of batches times per-batch duration, at a write rate the primary can absorb alongside roughly 1.2k writes per second of production traffic. The loop is throttled by replication lag and lock waits, not by how fast it can issue statements.
- Price the schema step by its lock rather than its statement duration. In PostgreSQL an ALTER TABLE taking ACCESS EXCLUSIVE waits for every open transaction on that table while later queries queue behind it, so a millisecond change issued during a thirty-second analytics query stalls that table for thirty seconds. Adding a nullable column with a non-volatile default avoids a rewrite from version 11; a new index wants CREATE INDEX CONCURRENTLY, which cannot run inside a transaction block and leaves an invalid index behind if it fails.
- Express the answer as a range whose endpoints each trace to a stated assumption, then name the cheapest experiment that collapses it, which is almost always running one real batch against the real table and multiplying.
- Commit to a checkpoint rather than a completion date: the day you report a measured number from that first batch. That is a promise you can keep under uncertainty, and it is what the asker actually needs in order to plan.
Follow-up
- How do you verify the backfill genuinely finished, given rows written by production traffic while it ran?
- Where does the backfill resume from after a worker is killed mid-batch, and what makes that resume point trustworthy?
- Your first batch comes back ten times slower than assumed. What do you tell the person waiting on the estimate, and when?
- 01
Walk through the most complex bug you hit during bring-up or emulation, and explain your debugging approach step by step.
- 02
Describe a time you optimised software for a small memory footprint or a strict latency requirement. What did you measure before and after?
- 03
How do you resolve a technical disagreement with a hardware or verification team during a project?
- 04
Tell me about a firmware or driver decision where you disagreed with a teammate. What data settled it?
- 05
Describe a technical decision you made and later reversed. What measurement changed your mind, and what did the reversal cost?
Is this an official Qualcomm interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Qualcomm. Rounds and questions reflect what candidates have reported, not a process Qualcomm has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult are the coding questions compared to standard software engineering interviews?
Candidate reports say the coding focuses on C fundamentals, memory management, arrays, linked lists and bit manipulation more than on complex abstract algorithm design. Medium-level algorithm problems do appear, but the reported emphasis is on language execution details, bitwise operations and memory efficiency. Prepare to write clean C for linked-list, bit-mask and two-pointer array problems. Be ready to say what each line does to memory, not only to pass the examples.
PracHub interview research ↗Can I use Python or Java during the technical interview?
Candidate reports say high-level languages are accepted in generic data-structure rounds, but most core software teams expect strong C or C++, because the job involves direct memory management and register-level programming. Ask your recruiter which language your rounds expect. If the team is driver, kernel or firmware work, practise in C even if another language is allowed.
PracHub interview research ↗What is the typical timeline from the initial screen to a final offer?
Candidate reports put the whole process at roughly three to six weeks, with five stages running from recruiter outreach to specialized technical rounds. Candidate reports also say the full loop is often scheduled within one to two weeks of passing the technical screen. Ask your recruiter for the current schedule, especially if you have another deadline.
PracHub interview research ↗What differentiates candidates who clear the process from those who get rejected?
Candidate reports say successful candidates can explain what happens at the machine level when their code runs. Candidates who struggle often have working code but cannot explain memory layout, stack versus heap allocation, pointers or concurrency safety. In practice, finish every answer with where the data lives, what the hardware or scheduler does with it, and what breaks if two threads or an interrupt get involved.
PracHub interview research ↗How much hardware knowledge does a software candidate need?
The reported questions include cache hierarchy and coherence, RISC versus CISC, memory-mapped register writes, interrupt handling from assertion to ISR, and bus protocols such as AXI, AHB, I2C and SPI. Prepare to explain how your code interacts with each of these: what a cache miss costs your loop, what a register write does on the bus, and what runs between an interrupt and your handler. The question bank for this role also includes timing closure, semiconductor fundamentals and MOSFETs, so ask your recruiter whether any of that applies to your team.
PracHub Software Engineer practice ↗What if the role is in verification, multimedia or ML infrastructure?
Candidate reports say specialized roles can replace generic data-structure problems with domain rounds, for example UVM/SystemVerilog for verification, computer vision pipelines for multimedia, or DSP algorithms. Related bank questions cover debugging a UVM environment, raw camera data processing and AI/ML compiler concepts. Confirm with your recruiter which domain applies, then give it its own preparation days.
PracHub Software Engineer practice ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-24 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-24 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-24