The Software Engineer role at Adobe spans product lines including Creative Cloud applications such as Photoshop, Illustrator and Premiere Pro, Document Cloud products such as Acrobat and Sign, the enterprise Adobe Experience Cloud, and the Firefly AI platform. Depending on the team, the work sits in cloud-native backend microservices, real-time collaboration engines, C++ desktop engines, Java or Scala services, or React web interfaces.
Reported questions follow that spread. Alongside standard data structures and algorithms, candidates describe C++ memory questions (a thread-safe shared pointer, a pool allocator), operating-system and database fundamentals, and design prompts shaped like the product surface, such as a serverless thumbnail service for uploaded assets and a real-time collaborative canvas. Frontend and web candidates report JavaScript internals and React questions on top of that.
Candidates report interviewing for engineering hubs including San Jose, Lehi, Noida, Bengaluru and Bucharest, and reports say stage counts vary somewhat by region and team. Treat the four rounds below as the reported shape of the loop and confirm your own with the recruiter.
Online Assessments
reportedCandidates describe a timed online assessment that mixes multiple-choice questions on core computer science (operating systems, DBMS, computer networks, aptitude) with coding problems. Candidates name HackerRank or CodeSignal as hosts, put the coding portion at two to three problems of LeetCode Medium to Hard difficulty, and report a recruiter screen before it. Prepare for cases the examples do not show, and pace the multiple-choice block, which candidates report is time-restricted. The reported array problems (rotating an array in place, trapping rainwater, the longest subarray with a sum divisible by k) are a good calibration set.
What to demonstrate
- Whether your solutions pass cases the examples do not show: empty input, a single element, negative numbers, and values that overflow a 32-bit integer
- Whether you can answer fundamentals questions on paging, indexing, and TCP versus UDP from recall rather than recognition
- Whether you pace across both sections so the coding problems get enough time
How to prepare
- Run timed sets that start with a block of CS multiple-choice questions followed by two coding problems, and record where the time went
- Write a small harness before each solution: the given examples plus empty, single-element and all-negative inputs, printing expected against actual
- Solve the reported array problems from a blank editor until each is automatic: three reversals for rotation, two pointers for rainwater, first-seen prefix remainders for divisible-by-k
Technical Conversations
reportedReported as discussions with senior engineers or hiring managers covering your resume projects, your technical background, and live problem-solving. Candidates report that live coding happens over screen share (HackerRank, Microsoft Teams or Zoom) and that searching online for syntax or library signatures is not allowed and may be treated as a policy violation. Prepare for two modes in one conversation: explaining a project you built down to its trade-offs, and coding in front of someone without autocomplete or documentation.
What to demonstrate
- Whether you can explain a project on your resume down to the constraint that shaped it, the alternative you rejected, and what you measured
- Whether you write working code in your chosen language from memory, including standard-library calls and their parameters
- Whether your narration keeps pace with your code so the interviewer can follow and redirect you
How to prepare
- For two resume projects, write the constraint, the rejected option, the before-and-after measurement and what went wrong; cut any claim you cannot defend under a follow-up
- Do timed problems in a plain editor with autocomplete off and no browser tab open, speaking your reasoning aloud
- List the ten standard-library calls you look up most in your language and drill them until the lookup is gone
Onsite Interview
reportedCandidates describe the onsite as multiple back-to-back technical sessions covering data structures and algorithms, low-level design and system design. Candidates add that the loop can include a domain-specific evaluation of your stack, such as React and TypeScript or C++ and Java, and that it may run over one or two days. Reported questions span graph and tree problems (Word Ladder with BFS, binary tree maximum path sum), C++ low-level design (a thread-safe shared pointer, a pool allocator), OS and database fundamentals, and product-shaped design prompts such as a serverless thumbnail service and a real-time collaborative canvas. The reports do not tie these questions to specific sessions, so prepare each category to full depth.
What to demonstrate
- Whether you state the approach and its time and space complexity before coding, then test boundary conditions yourself
- Whether a low-level design answer holds up as code: ownership, copy and move semantics, and which operations are thread-safe
- Whether a system design answer starts from functional and non-functional requirements, interfaces and data model before scale, caching and fault tolerance
- Whether you can explain the fundamentals under the code, such as what happens on a page fault or why a B-tree index serves range queries
How to prepare
- Implement a shared pointer with an atomic reference count and a pool allocator with a free list, and write tests for self-assignment and last-owner release
- Take two reported design prompts to API and data-model depth, naming one failure mode and its recovery for each
- Solve Word Ladder (returning the shortest sequence itself) and maximum path sum from memory, stating complexity and the edge case each is most likely to fail (an unreachable end word, an all-negative tree)
Managerial Discussions
reportedReported as conversations on behavioral alignment, collaboration and vision for business impact, and described by candidates as an engineering manager or director round. Reported prompts ask about leading a complex project and its technical trade-offs, handling conflicting priorities from leadership or cross-functional teams, responding to critical feedback or a production failure, and how you demonstrate the values named in the prompt (Creating the Future, Owning the Outcome, Raising the Bar, Be Genuine). A values answer that repeats the value names without a story adds nothing, so attach each one to something you did.
What to demonstrate
- Whether each story shows a decision you made, with the trade-off and the result, rather than what the team did around you
- Whether a conflicting-priorities answer shows how you decided and who you told, not only that it was resolved
- Whether you connect your technical work to its effect on users or the business in concrete terms
How to prepare
- Write STAR outlines for the reported prompts and for the behavioral topics in PracHub's question bank: building team trust, persisting with a doubted initiative, a major setback, working with a product manager
- For each of the four named values, pick one specific story and one sentence on what you did, without restating the value
- Have someone ask why four times on your weakest story, and re-read the project material where your answer runs out
8 candidate reports. Individual accounts describe a particular role and hiring cycle.
Adobe Account Executive Interview Experience: prospecting task and no closure
The process lasted about four rounds and felt more demanding than a standard recruiter-to-manager path. It began with a discovery-style conversation and a peer interview. I was also asked to prospect for a meeting with the hiring manager. That task was awkward because the hiring manager did not answer calls and had a private LinkedIn profile, so outreach was not straightforward even though the pr…
Read full experienceAdobe Account Executive interview: supportive first round followed by radio silence
The process felt normal and contained, with about three rounds. It began with a recruiter conversation, then a task, and finally a meeting with the hiring manager. Communication ran smoothly at first, and the recruiter was especially supportive. I received helpful, actionable feedback instead of vague notes. After the first round, the experience did not continue that way. I got nothing back. Ther…
Read full experienceAdobe Research Analyst Interview Experience: One-hour research conversation
After a recruiter touchpoint, I had one technical conversation with a team member. It lasted an hour and stayed mainly focused on the research I had already done and where I wanted to take it during the internship. The process moved quickly. I had the interview and received a decision about two weeks later. There was not much jumping between steps. It was essentially a discussion about my work an…
Read full experienceAdobe Software Engineer Interview Experience — Five Relaxed Rounds Built Around OOP and API Design
This one felt pretty comfortable to interview with — slow pace, none of that being-chased-the-whole-time feeling. Each round was an hour, and in some rounds close to half the time was just chatting. The problems were medium-to-easy, but they really like steering things toward object-oriented design and code design — the questions here are different from what other companies ask. A quick note: I'm…
Read full experienceAdobe Software Engineer Interview Experience — Scala Trivia, Then a Surprise LeetCode Classic
This is one of the many applications I scattered around blindly. I applied to GenStudio on the DX team (people on the forum say DX is a "poison team," same as AEP?). When I applied, it happened to line up with Adobe's legendary summer break, so by the time HR came back from vacation and finally reached out to me, I'd already piled up several rejection letters from other places, hah, wry laugh. Th…
Read full experiencePracHub editorial advice for the preparation topics above.
Running out of time on the online assessment's coding problems after the multiple-choice block
The reported assessment pairs time-restricted CS multiple-choice questions with two to three coding problems, and candidates warn about exactly this. Before starting, look at both sections and set a stopping point for the multiple-choice block; skip any question you cannot answer on first read and return if time remains. Rehearse it in at least two full timed runs so the split is a habit rather than a decision made under pressure.
Searching for syntax during live coding, or depending on autocomplete you will not have
Candidates report that live rounds run over screen share and that searching online can be treated as a policy violation. Pick one language, practise in a plain editor with suggestions off, and drill the calls you usually look up: sorting with a comparator, string split and join, heap operations, ordered-map lookups. If you forget a signature, say what you assume it does and write a one-line wrapper rather than guessing silently.
Treating CS fundamentals as an entry-level topic you can skip
Reports say OS, database indexing, threading and language internals come up across experience levels. Prepare to explain virtual memory and TLB lookups, LRU versus MRU replacement, deadlock conditions and a producer-consumer queue, B-tree versus hash indexes, TCP versus UDP, and in C++ destructors, smart pointers and delete versus delete[]. Explain each aloud without notes; recognising a term in a multiple-choice option is not the same as explaining it to an interviewer.
Answering the shared-pointer or allocator question with boxes instead of code
These reported questions are low-level design, so expect to write the class. For a shared pointer, show the control block, the atomic increment on copy, the decrement with acquire-release ordering that deletes when the last owner releases, move semantics and self-assignment. State the guarantee precisely: the count is thread-safe, but the pointee and concurrent writes to one shared-pointer object are not. For a pool allocator, show the free list and when you go back to the OS for more memory.
Behavioral answers that describe the team's project without your own decision in it
Reported managerial prompts ask about a project you led and its trade-offs, conflicting priorities, and critical feedback or a production failure. For each story, name the decision you personally made, the option you rejected, the result with a number you can qualify, and what you changed afterwards. For the values prompt, attach a concrete example to each named value instead of reciting them.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Find the longest contiguous subarray whose sum is divisible by a targe…
Find the longest contiguous subarray whose sum is divisible by a target integer.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- Which test case would catch an off-by-one here?
- What is the worst case, and how likely is it on real data?
Implement a solution to find the shortest transformation sequence from…
Implement a solution to find the shortest transformation sequence from a start word to an end word using a dictionary (Word Ladder using BFS).
Approach
- Name the brute-force solution and its complexity before improving on it.
- 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?
Solve the Rainwater Trapping problem using a two-pointer or dynamic pr…
Solve the Rainwater Trapping problem using a two-pointer or dynamic programming approach.
Approach
- 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.
- Choose the data structure from the access pattern, not from familiarity.
Follow-up
- How does this change if the input no longer fits in memory?
- Which test case would catch an off-by-one here?
Given a binary tree, find the maximum path sum between any two nodes (…
Given a binary tree, find the maximum path sum between any two nodes (LeetCode 124 - Binary Tree Maximum Path Sum).
Approach
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Parse and verify a timestamped multi-signature webhook header
An inbound webhook carries a signature header of at most 1 KiB shaped t=<unix seconds>,v1=<64 hex chars>, with up to five v1 values during secret rotation and possibly unknown scheme keys. You hold the raw request body bytes and the currently active signing secrets. Write the parser and the verifier: accept when any active secret reproduces a signature and the timestamp is within a five-minute tolerance in either direction, reject otherwise. Single left-to-right pass over the header, no regular expression. State what is inside the MAC and why.
Approach
- Parse in one scan: split on
,, then on the first=only, since a value may itself contain=under a future scheme. Accepttexactly once and treat a secondtas a reject rather than last-wins. Push everyv1onto a short list and ignore any other key, so av2can be introduced later without breaking this verifier. - Say what is signed: HMAC-SHA256 over the exact byte string
<t>.<raw body bytes>, yielding 32 bytes or 64 hex characters. The timestamp sits inside the MAC because otherwise an attacker replays yesterday's body with its still-valid signature and only has to edit the header timestamp. - Hash the bytes as received. Verifying against a re-serialised JSON body is the usual defect: key order, whitespace and number formatting all change the bytes while the parsed objects compare equal, so signatures fail for honest senders and the popular 'fix' is to stop checking.
- Compare in constant time over fixed-length digests. Decode the hex to 32 bytes, accumulate
acc |= a[i] ^ b[i]across the whole length, and testacc == 0at the end. Evaluate every candidate without an early exit; at five candidates that is five HMACs over the body, linear in body size and negligible beside the network. - Apply the tolerance as a two-sided bound, rejecting when
|now - t| > 300seconds. A sender whose clock runs ahead of yours is an ordinary case, and an unbounded future timestamp is a free replay window. - Complexity: O(L) over the header producing k candidates, plus k HMACs at O(|body|) each. Space is O(k) beyond the body itself. Do the cheap rejections, including the tolerance check, before any cryptography runs.
Worked solution 15 min
- Write the grammar on one line before coding:
header := field (',' field)*,field := key '=' value, split on the first=only. - Implement the parser to return
{t: int, v1: [hex, ...]}, rejecting a missingt, a duplicatet, anyv1that is not 64 hex characters, and a header over 1 KiB, all before any cryptography runs. - Implement the verifier: for each active secret compute
HMAC-SHA256(secret, f'{t}.'.encode() + raw_body), compare it in constant time against each parsedv1, and OR the results with no early exit. - Test with a valid signature; the same body with
tmoved 400 seconds into the past; the same body witht400 seconds into the future; a header carrying an unknownv2=alongside a validv1; and a body re-serialised with different JSON key order.
Follow-up
- The body is 40 MB. What changes about where you verify, and what can you do before the whole body has arrived?
- A customer reports that signatures fail for exactly the requests whose body contains a non-ASCII character. What is your first hypothesis?
- How do you rotate the signing secret with no failed deliveries, and how long do both secrets stay live?
Paginate a tenant's delivery export without skipping rows
A customer exports webhook_delivery: delivery_id (bigint identity), subscription_id, tenant_id, event_id, status, attempt_count, next_attempt_at, created_at, delivered_at, updated_at. The endpoint runs select ... where tenant_id = $1 order by created_at desc limit 100 offset $2, and customers report rows missing from exports taken while new deliveries are being inserted. Write the replacement query and the index that supports it, paging a tenant's deliveries newest first at constant cost per page. State why updated_at cannot be the cursor column.
Approach
- Name the defect precisely. OFFSET is a position in a result set that is recomputed on every request, so a row inserted ahead of the window shifts everything back by one and the next page starts after a row the client never received. Nothing errors and no identifier gap appears, so the loss is silent.
- Replace the position with a value predicate over a stable, unique, indexed ordering:
where tenant_id = $1 and (created_at, delivery_id) < ($2, $3) order by created_at desc, delivery_id desc limit 100. The row comparison is load-bearing: created_at alone is not unique, so ties straddling a page boundary are dropped or repeated, which is the same bug in a smaller window. - Index
(tenant_id, created_at, delivery_id). PostgreSQL scans a btree in either direction, so an all-DESC ORDER BY is served by an ASC index read backwards and no DESC modifiers are needed; they only matter when the ORDER BY mixes directions. Confirm the plan has no Sort node above the index scan, or the LIMIT stops being an early exit. - Price both forms: keyset is one index descent plus 100 adjacent leaf entries per page, constant regardless of depth, while OFFSET still produces and discards every skipped row, so page N costs time proportional to N times the page size and a deep page on a large table goes from milliseconds to seconds.
- Rule out updated_at as the cursor from the precondition, not from taste: a cursor column must never change value for a row already paged past. updated_at moves on every delivery attempt, so a row the client already emitted re-enters a later page and is exported twice. created_at and delivery_id are immutable, which is the whole qualification.
Worked solution 20 min
- Load about 50k deliveries for one tenant, then walk them with the OFFSET query while a writer inserts 10 rows/second, collecting every returned delivery_id.
- Compare the distinct ids collected against the set of ids that existed when the walk started, and record the shortfall.
- Repeat the walk with the keyset query and confirm every pre-existing id is returned exactly once.
- Run
explain (analyze, buffers)on page 1 and page 500 of each form and compare shared buffer hits.
Follow-up
- The client wants a snapshot as of one instant rather than a live tail. Compare a repeatable-read transaction held open, an added
created_at <= $snapshotbound, and a materialised export table. - A retention job deletes deliveries older than 90 days. What does a client mid-walk see, and does keyset pagination help at all?
- The customer wants to resume an export from yesterday's last cursor. What must be true of the cursor for that to be safe?
Model credential revocation so history survives the delete
tenant_api_key stores key_id, tenant_id, workspace_id, name, key_prefix, secret_hash, scopes text[], status (active, revoked, expired, compromised), auth_version, created_at, expires_at, last_used_at, revoked_at, revoked_reason. Rotation inserts a new row and revocation never deletes, because an incident review asks which credential served a request last quarter. Write the constraints that enforce: a label is unique only among a tenant's live keys, revoked_at and status can never disagree, and scopes is never empty. Then write the authentication lookup predicate, and name one column in this table that must stay out of it.
Approach
- Reach for a partial unique index rather than a plain UNIQUE:
create unique index on tenant_api_key (tenant_id, name) where revoked_at is null. Any number of revoked rows may share a label, the live namespace stays unique per tenant, and the revoked majority is not in the index at all, so it stays small on a table that only grows. - Tie the nullable timestamp to the enum so the two cannot drift:
check ((revoked_at is not null) = (status in ('revoked','compromised')))andcheck ((revoked_at is null) = (revoked_reason is null)). A revocation that records no reason is the one an incident review cannot use. - Write the emptiness check as
check (cardinality(scopes) > 0), notarray_length(scopes, 1) > 0. array_length returns NULL for an empty array, a CHECK constraint passes when its expression is NULL, so the array_length version accepts exactly the value it was written to reject. - Make the lookup a single index probe with every liveness condition inside it:
where secret_hash = $1 and revoked_at is null and (expires_at is null or expires_at > now()) and auth_version = $2, backed by a unique index on secret_hash. Nothing is filtered in application code, so there is no path that forgets a clause. - Keep last_used_at out of that predicate. It is written asynchronously and is allowed to lag by a minute, so it is a usage signal; feeding it into an authorisation decision makes the decision depend on a write that may be late, batched away or lost.
- Flag the modelling smell while you are here:
expiredis derivable fromexpires_at < now(), so storing it as a status obliges a job to keep it true and guarantees the column is wrong between the expiry instant and that job's next run. Derive it in the predicate; keep the stored status for states that are decisions rather than clock readings.
Follow-up
- Rotation issues a replacement while the old key stays live for a 30-day overlap. What does the uniqueness rule become, and what does the UI show to tell two same-named keys apart?
- A password reset bumps the principal's auth_version. No row in this table changed. How does the next request fail, and what query counts how many keys that bump just killed?
- A key turns up in a public repository. Which columns let you find it, and what do you write to the row?
Implement a custom shared pointer class in C++ with reference counting…
Implement a custom shared pointer class in C++ with reference counting and thread safety.
Approach
- Name the read and write paths separately; they rarely have the same bottleneck.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the failure you are designing for, then the recovery path.
Follow-up
- What would you drop to keep the system up under load?
- What breaks first when traffic grows ten times?
Design a serverless thumbnail generation service capable of processing…
Design a serverless thumbnail generation service capable of processing millions of high-resolution asset uploads concurrently.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- State the consistency you need, and where you are willing to be stale.
- Choose a partition key and say what query it makes expensive.
Follow-up
- What would you drop to keep the system up under load?
- What breaks first when traffic grows ten times?
Design and implement a client-side memory cache system with key expira…
Design and implement a client-side memory cache system with key expiration and dynamic size limits.
Approach
- Work from the requirement backwards to the design.
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Make run creation safe when the client times out and retries
POST /v1/runs inserts a job_run row and dispatches a sandbox. The caller is a customer's CI pipeline with a 10-second timeout and three automatic retries. A run that takes 12 seconds to start returns after the client has already given up, so the retry starts a second sandbox and bills it. Redesign the endpoint: the key the client sends, its scope and storage, what happens when the same key arrives with a different body, what happens when a retry arrives while the first request is still in flight, and how long the key stays honoured.
Approach
- Name the defect before designing: the client's timeout is an unknown outcome, and the naive shape gives it no way to ask whether the earlier call landed, so its only choices are to duplicate the run or to drop it.
- Require an
Idempotency-Keyheader scoped to (tenant_id, key) rather than to the credential, so a rotated or replaced credential still replays. Store the key with a request fingerprint, SHA-256 over method, path and the canonicalised body, plus state, the stored response status and body, and the resulting run_id. - Make the claim a write rather than a read: insert the key row inside the same transaction as the run under
unique (tenant_id, idempotency_key). The loser of a concurrent race takes a unique violation and then reads the winner's row, which is what makes the duplicate case deterministic instead of timing-dependent. - Define three outcomes precisely. Same key, same fingerprint, completed: replay the stored response with a header marking it a replay. Same key, different fingerprint: 422 with an
idempotency_key_reusecode, never the stored response. Same key still in flight: 409 with Retry-After, because blocking the second caller holds a connection for the duration of someone else's request. - Close the dispatch gap with an outbox row committed alongside the run and a relay that enqueues it. Commit-then-publish loses the dispatch if the process dies in between; publish-then-commit hands a worker a run_id that does not exist yet.
- Set retention from the client, not from storage cost: the key must outlive the caller's worst-case total retry window, so publish a number such as 24 hours and state that a key reused after expiry legitimately creates a second run.
Worked solution 30 min
- Draw the timeline of the failing case: commit at t=11s, client abandons at t=10s, retry at t=10.1s, and mark where the second sandbox starts.
- Write the idempotency table DDL with the unique constraint and the fingerprint column, then the single transaction that inserts both rows.
- Enumerate the four arrival cases (first, replay, conflicting body, in-flight) and write the exact status, headers and body for each.
- Add the outbox row to the same transaction and describe the relay's at-least-once behaviour and why the worker must tolerate a duplicate dispatch.
- State the retention horizon and the sentence that goes in the public docs about key reuse after expiry.
Follow-up
- The SDK generates a fresh key on every attempt rather than reusing one. What in your response surface makes that visible instead of silently doubling the bill?
- How does this interact with job_run.parent_run_id: is an automatic retry of a failed run the same object as a client retry of the request?
Gateway p99 spikes on a five-minute cadence
edge-gateway caches each credential-to-authorisation-context decision for five minutes. p99 sits at 6 ms except for a spike to 900 ms roughly every five minutes, worst in the region with the most pods, and control-plane CPU and read latency rise in step with it. The error rate stays near zero. Customers are told a revoked credential stops authorising within 60 seconds. Give the ordered checklist that identifies the mechanism, and a fix that removes the spike without weakening the 60-second bound.
Approach
- Test periodicity before anything else: take the spike timestamps modulo the TTL in seconds. A tight cluster at a fixed offset means expiry phase, while traffic-driven spikes scatter.
- Overlay pod start times. Entries filled at first request inherit the phase of the pod that filled them, so a cohort of pods deployed together expires together and the amplitude should track cohort size rather than tenant count.
- Separate a herd from a capacity shortfall by measuring control-plane requests per second during a spike against baseline. A stampede shows a step of roughly (pods x hot keys) for one interval with hit rate collapsing to near zero, not a gradual climb that would indicate the dependency is simply undersized.
- Apply three independent controls: randomise each key's TTL by a factor drawn uniformly from something like 0.8 to 1.0 so cohorts de-phase; coalesce concurrent misses per key per pod so exactly one refresh is in flight; and serve the stale value while that refresh runs so a miss costs the stale read rather than the dependency's queue.
- Bound staleness against the published contract rather than against comfort: serve-stale is admissible only up to the 60-second revocation bound, so the TTL floor and the stale window together must stay inside it, and the published invalidation must delete the entry rather than schedule a refresh.
- Decide in advance what a miss does when the control plane is unreachable, because that is now the only uncached path: failing closed converts a dependency outage into a total outage, while extending stale service past the bound breaks the revocation promise. Pick one and configure it explicitly.
Follow-up
- Publish-subscribe invalidation is lossy under a partition. Given that, what actually enforces the 60-second bound, and what number would you put in the contract if asked to defend it?
- One tenant's key is hot enough that a single pod's coalesced refresh still matters. What changes?
- Would a shared cache tier in front of the control plane help or shift the problem, and what new failure does it add?
For a candidate senior enough that the loop turns on design and judgement rather than on whether the coding round gets finished. Five days build one system properly and then stress it; coding gets a single maintenance day, on the assumption that the risk at this level is an unexamined tradeoff rather than a missed algorithm.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Online assessment: array and prefix-sum problems under a clock
- Solve the reported array problems timed, from a blank editor: rotate an array in place with three reversals (O(n) time, O(1) space), trapping rainwater with two pointers, and the longest subarray whose sum is divisible by k using first-seen prefix remainders.
- For divisible-by-k, write the edge cases before coding: negative numbers (normalise each remainder into 0..k-1), a prefix remainder of 0 (seed the map with remainder 0 at index -1), and an answer spanning the whole array.
- Before each submission, run a harness with the given examples plus empty and single-element inputs.
- Do one timed run that starts with a block of OS, DBMS and networking multiple-choice questions, then the coding problems, and note where the time went.
Deliverable: Three reported array problems solved from memory with a test harness, plus a note on how much time the multiple-choice block cost you.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Graphs and trees for the onsite algorithm sessions
- Word Ladder: BFS from the start word, generating neighbours by substituting each position with each letter and checking a set of dictionary words. When a word is first enqueued, mark it visited and record its parent in a map. State the cost as roughly N x L x 26 candidates, each O(L) to build and hash.
- Once the end word is reached, walk the parent map back to the start word and reverse it to return the shortest transformation sequence, or an empty result if the end word is unreachable. Returning only the sequence length (the BFS level count) is the common variant.
- Binary tree maximum path sum: a post-order pass that returns the best downward gain, max(0, child gain), and updates a global best with node + left + right. Test an all-negative tree.
- Work the tree and graph topics in PracHub's question bank: BST validation with bounds, level-order traversal, lowest common ancestor when both nodes may be missing, and task ordering with prerequisites via topological sort that reports a cycle.
Deliverable: Word Ladder returning the shortest sequence via a parent map, maximum path sum with stated complexity, and one topological sort that detects a cycle.
Practice prompt ↗Practice prompt ↗03CS fundamentals for the assessment and the onsite
- OS: explain virtual memory, paging, TLB hits and misses, and LRU versus MRU page replacement, then walk through a page fault step by step aloud.
- Threads: list the four deadlock conditions and how lock ordering breaks one; implement a bounded producer-consumer queue with a mutex and two condition variables, waiting in a loop.
- Databases: B-tree versus hash indexes and which queries each serves; then work the guide's worked SQL exercise on keyset pagination and the SQL topics in PracHub's question bank (average grade per subject with NULL-safe aggregation, filtering students by grade).
- Networking: TCP versus UDP, and how HTTP/2 multiplexes streams over one connection.
Deliverable: One page of fundamentals notes you can explain without references, and a working bounded queue.
Practice prompt ↗Practice prompt ↗04Low-level design, written as code
- Implement the reported shared pointer: a control block with an atomic count, increment on copy, fetch_sub with acquire-release ordering on release and delete when the previous count was 1, plus copy and move assignment handling self-assignment.
- Explain delete versus delete[]: a hand-written shared pointer with no array specialisation, or a std::shared_ptr<T> built from new T[n], must be given a custom deleter that calls delete[]; since C++17, std::shared_ptr<T[]> calls delete[] by default.
- Build the reported client-side cache with key expiration and a size limit: a hash map plus a doubly linked list for LRU order, expiry checked on read with a periodic sweep, and a stated rule for which entry goes first when both limits apply.
- Sketch a fixed-size pool allocator: a free list threaded through unused blocks so allocate and release are O(1) and system calls happen only when the pool grows.
Deliverable: A compiling shared pointer and a TTL-plus-LRU cache, each with tests for self-assignment, expiry and eviction order.
Practice prompt ↗Practice prompt ↗Worked solution ↗05System design from the reported prompts
- Serverless thumbnail service: upload to object storage, one event per upload, function workers producing each size, output keyed by asset id and size so a retried job overwrites rather than duplicates. Use the guide's worked design exercise on idempotent retries for the same reasoning.
- Real-time collaborative canvas: requirements first, then the trade-off between operational transformation and CRDTs, presence, persistence, and two users editing the same object.
- Q&A assistant on an enterprise platform (a design topic in PracHub's question bank): retrieval over customer content, per-tenant scoping, and where latency goes.
- Open every design with functional and non-functional requirements, APIs and the data model before scale, caching or fault tolerance.
Deliverable: Two designs taken to API and data-model depth, each with a named failure mode and its recovery path.
Practice prompt ↗Practice prompt ↗06Technical conversations: your projects and live coding
- For two resume projects, write the constraint, the rejected alternative, the measurement before and after, and what broke; rehearse each until you can take an unplanned follow-up.
- Do a live coding session over screen share with autocomplete off and no search, narrating as you go; the guide's worked coding exercise on parsing a signed webhook header is a good single-pass parsing drill.
- If your target team is web-facing, add the reported frontend set: a React counter hook with pause, resume and reset that clears its interval on pause and unmount, event loop ordering of microtasks and macrotasks, and a request handler with client-side throttling and retry with backoff.
Deliverable: Two project write-ups that survive follow-ups, and one recorded live-coding session you have reviewed.
Practice prompt ↗Practice prompt ↗07Managerial discussions and a full mock
- Write STAR stories for the reported prompts: a complex project you led and its trade-offs, conflicting priorities from leadership or other teams, critical feedback or a production failure, and your strengths and weaknesses.
- Map one specific story to each value named in the reported values prompt (Creating the Future, Owning the Outcome, Raising the Bar, Be Genuine).
- Run a mock with one coding problem, one design prompt and one behavioral question, and ask the interviewer to change a requirement partway through the design.
Deliverable: A story bank covering every reported behavioral prompt, and mock notes recording what changed under the new requirement.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Candidates report behavioral questions in the managerial discussions: leading a complex project, conflicting priorities, critical feedback or a production failure, and a prompt built around four named values. Prepare stories where you made the decision, name the trade-off you accepted, give a result you can qualify with a number, and say what you changed afterwards. For the values prompt, one concrete story per value beats a restatement of the list.
How do you handle a scenario where leadership or cross-functional team…
How do you handle a scenario where leadership or cross-functional teams ask for conflicting project priorities?
Approach
- Give the blast radius: what could have broken, and what you measured.
- Close with what you would do differently, concretely.
- 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?
Share an experience where you received critical feedback or faced an u…
Share an experience where you received critical feedback or faced an unexpected system failure in production, and how you responded.
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- How did you know your change caused the improvement?
- What did you decide not to do, and why?
Own the incident where invoices undercounted metered usage
A metering consumer acknowledged each batch before committing the fold into usage_rollup_hourly. A rolling deploy restarted consumers mid-batch for two hours; roughly 1.4M usage_event rows were acknowledged and never folded, and 61 invoices sealed against the resulting rollups before anyone noticed. Take the owner's role. Describe an incident of comparable blast radius you owned: how it surfaced, the query that sized the loss, what you stopped first, and how the money was corrected. Give a wall-clock timeline and one thing you got wrong while it was still live.
Approach
- Open with the invariant that broke and the direction of the error, because they determine everything else: acknowledging before committing makes the consumer at-most-once, so this loses events rather than duplicating them, and loss raises no error anywhere. A listener who hears 'we lost revenue silently' knows immediately why detection took two hours.
- Size it with a stated reconciliation rather than an adjective: sum(quantity) from usage_event grouped by (tenant_id, sku, hour of occurred_at) over the window, against usage_rollup_hourly.quantity_sum on the same keys, filtered to environment='production' because staging and sandbox are metered but not billed. Then bisect by hour and tenant until single cells explain the gap. Say how long that ran and whether a replica could serve it while the incident was live.
- Separate mitigation from fix and say which came first. Mitigation is holding the sealing job, because a sealed row is frozen by design and every minute of sealing converts a recoverable rollup into an invoice correction. The fix is moving the acknowledgement after the commit, which re-introduces duplicates that the dedup check on (tenant_id, idempotency_key) must now absorb.
- State the correction path in the domain's own terms: sealed periods are never edited, so each affected tenant gets an adjustment line on the next invoice with kind='adjustment' and voided_by_line_id pointing at the line it reverses, priced against the same rate tier and carrying the watermark it priced against. That is four separate numbers — tenants affected, minor units, the cycle the adjustment lands in, and when customers were told.
- Close on one prevention control with its cost, not five: a per-hour reconciliation comparing raw sum to rollup sum that pages above a threshold. Name the threshold and the false-page rate you accepted, because a detector nobody will keep staffed is not prevention.
- Name a mistake you made inside the response window — the wrong first hypothesis, a mitigation that made it worse — rather than a design mistake from six months earlier. That is the part candidates rehearse away and interviewers weight heavily.
Follow-up
- Your fix moves the acknowledgement after the commit. What breaks now, and what absorbs it?
- One undercharged tenant has since churned. Do you bill them, and who decides?
- How would you have caught this in ten minutes instead of two hours, and what would that detector cost you in pages per week?
- 01
Describe a complex project you led, detailing the key technical trade-offs and architecture decisions you made.
- 02
How do you handle a scenario where leadership or cross-functional teams ask for conflicting project priorities?
- 03
Share an experience where you received critical feedback or faced an unexpected system failure in production, and how you responded.
- 04
How do you demonstrate Adobe's core values (Creating the Future, Owning the Outcome, Raising the Bar, Be Genuine) in your daily engineering work?
- 05
What are your strengths and weaknesses? Give an example of each and what you are doing about the weakness.
- 06
Describe a time you and a product manager disagreed on a feature. How did you reach a decision?
Is this an official Adobe interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Adobe. Rounds and questions reflect what candidates have reported, not a process Adobe has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult are the algorithmic coding questions at Adobe?
Candidate reports put the coding questions between LeetCode Medium and Hard. Aim for clean, working code with edge cases handled, not only the optimal complexity. Reported examples include Word Ladder, trapping rainwater, binary tree maximum path sum and the longest subarray with a sum divisible by k, so calibrate on graph, tree, two-pointer and prefix-sum problems.
PracHub interview research ↗Can I search online or access reference docs during live coding rounds?
Reports say no. Live coding is described as happening over screen share on HackerRank or on Microsoft Teams or Zoom, and searching for library signatures may be treated as a policy violation. Practise in one language with autocomplete off until standard syntax and library calls come from memory, and if you are unsure of a signature, state your assumption aloud.
PracHub interview research ↗Does Adobe test CS fundamentals like OS and DBMS for experienced roles?
Candidate reports say yes: operating systems, database indexing, threading and object-oriented language internals come up across experience levels, both as multiple-choice questions in the online assessment and in later conversations. Reported topics include virtual memory, paging and TLB hits, page replacement, C++ destructors and smart pointers, B-tree and hash indexes, deadlock prevention, and TCP versus UDP.
PracHub interview research ↗What is the typical timeline from initial screen to final offer decision?
Reports vary. The round summary gives roughly three to five weeks across four rounds, while other candidate accounts range from two to six weeks depending on team and regional scheduling. Ask your recruiter for the expected gap after the online assessment so you can plan preparation around it.
PracHub interview research ↗What is in the Adobe online assessment?
Candidates describe multiple-choice questions on core computer science (operating systems, DBMS, computer networks and aptitude) combined with two to three algorithmic coding problems of Medium to Hard difficulty, hosted on HackerRank or CodeSignal. Reports warn that the multiple-choice section is time-restricted, so pace it and leave room for the coding problems.
PracHub Software Engineer practice ↗How are candidates matched to specific product teams?
Candidates describe team matching happening either before interviewing for a specific requisition or after a general panel loop. Either way, state your stack preference (for example C++ engine work, React frontend or Java backend) to your recruiter early, and prepare the stack-specific material that goes with it.
PracHub Software Engineer practice ↗Do frontend and web candidates get different questions?
Reports say web-focused candidates also get JavaScript and React depth: closures, event loop ordering and scope binding, Promises versus async/await versus callbacks, a custom React counter hook with pause, resume and reset, an API request handler with client-side throttling and retry, and a client-side cache with expiration and size limits. Prepare these alongside the general algorithms material, not instead of it.
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