Software Engineers at Docusign work on products built around the Docusign Agreement Cloud. The source notes give core eSignature infrastructure, API integrations for partners and front-end performance as examples of the work, and they describe collaboration with Product, Design and Sales. The listed responsibilities cover the full development lifecycle: design, coding, testing and deployment, code review and automated testing, troubleshooting production issues, and technical documentation.
The notes name must-have skills: strong command of at least one modern language (Java, Python, TypeScript or React, depending on team), a solid grasp of data structures and algorithms, and experience with API development and RESTful services. Nice-to-haves are a cloud platform (AWS, Azure or GCP), distributed systems architecture, and CI/CD pipelines. If you apply for a full-stack seat, the notes warn that you may be asked to design a UI component and the API behind it in the same loop.
Candidates report three stages: a recruiter screen, a series of technical rounds mixing coding and system design, and behavioral discussions with hiring managers and peer engineers. Reported coding questions are practical, such as parsing JSON with edge cases, handling API response statuses and explaining the complexity of your own code. Reported design questions cover a high-traffic URL shortener, multi-region systems, database trade-offs, and consistency versus availability. Some candidates say interviewers switch without warning from algorithms to system design or to a deep dive into a past project, so practise moving between those levels in one sitting.
Recruiter Screen
reportedThe source notes describe this as a first call with a recruiter about your background and fit for the role. Use it to learn which team the seat is on and which stack it uses. The notes mention React for front-end work and Java, Python or TypeScript for back-end work, depending on team. They also say full-stack candidates may have to design a UI component and its API in the same loop. Ask whether the technical rounds include system design at your level. Have a specific answer ready for why you want Docusign. 'Why are you interested in Docusign specifically compared to other tech companies?' is a reported behavioral question, and a generic answer is easy to spot at any stage.
What to demonstrate
- Whether your background matches the must-haves in the notes: one modern language, data structures and algorithms, and API development with RESTful services
- Whether you give a concrete reason for wanting to work on agreement and eSignature software, rooted in work you have done
- Whether your level and target team are clear enough to plan the rest of the loop, including how much system design it should include
How to prepare
- Mark every line of the posting as done, adjacent or new. For each adjacent line, write one sentence naming the closest thing you have built
- Write a two-sentence why-Docusign answer tied to your own work, such as API integrations, document or workflow systems, front-end performance, or systems where correctness and security matter
- Bring these questions: which team and stack, whether system design is in the loop at your level, and whether full-stack means designing the UI and the API in one interview
Technical Rounds
reportedThe source notes describe the technical rounds as a series of interviews mixing coding assessments and system design discussions. Some candidates report interviewers moving mid-interview from algorithms to design or to a deep dive into a past project. Reported coding questions for the role are practical: parse a JSON object and handle edge cases, solve a string manipulation problem, write a script that calls an API and handles different response statuses, handle asynchronous programming in a distributed system, and explain the time and space complexity of the code you just wrote. Reported design questions include a URL shortener for high traffic, a multi-region low-latency system, a system for large amounts of data, database choice trade-offs, and keeping consistency and availability in a distributed environment. Candidate reports put coding difficulty at easy to medium, with more weight on explaining your reasoning than on trick questions. Clarify first, state your approach before you type, handle errors explicitly, and be ready to switch levels when the interviewer changes scope.
What to demonstrate
- Whether you clarify requirements and edge cases before coding, such as empty or malformed JSON, nested structures, unexpected types, and non-2xx responses
- Whether your code is modular and handles errors explicitly instead of covering only the one example given
- Whether you can state and justify the time and space complexity of your own solution without being prompted
- Whether a design answer includes a data model, a database choice with its cost, and an explicit consistency-versus-availability decision, rather than stopping at boxes
How to prepare
- From a blank file, write a JSON parsing or validation function and an HTTP-call helper, each with an edge-case list written before the code. The bank's Design a JSON Schema Validator is close practice
- After every practice problem, say the complexity out loud and name the bottleneck before you check any reference
- Design a URL shortener and a paginated list UI with its API end to end: endpoints, schema, read and write paths, and one SQL-versus-NoSQL decision with what it gives up
- In a mock, have a partner move you from a coding problem to a project deep dive partway through, and rehearse the sentence you will use to change levels
Behavioral Discussions
reportedThe source notes describe these as interviews with hiring managers and peer engineers about team fit and collaboration. They advise the STAR method, with the focus on your own contribution and its impact on the business. Reported prompts: a technical disagreement with a peer and how you resolved it, a challenging project you led and its business impact, how you handle ambiguous requirements, a time you mentored a junior engineer or helped a teammate, and why Docusign rather than another tech company. Some candidates report interviewers moving to a deep dive into a past project. Each story therefore needs to hold up through several follow-ups: the constraint that ruled out the obvious option, the part you built or decided yourself, and a result you can state accurately. If a follow-up challenges your decision, stay collaborative and explain the reasoning instead of defending the outcome.
What to demonstrate
- Whether each story draws a clear line around your own contribution that holds up when asked directly who made the decision
- Whether you state impact as a result someone could verify, such as latency, incidents, delivery date or adoption, rather than as an adjective
- Whether the disagreement and ambiguity stories show how you reached a decision (the evidence, the trade-off, who agreed) and not only that it ended well
How to prepare
- Build one STAR story for each reported prompt. Keep Situation and Task to two sentences and spend most of the answer on Action
- Replace every first-person plural in your stories with 'I' or a named role, and check that each story still holds together
- For the project story, list why you chose each technology, the trade-offs you accepted, and what you would build differently today
- For the mentoring prompt, prepare what the other person could do on their own afterwards. The approach notes on the drill 'Unblock an engineer on a job run that finished twice' show one way to structure it
8 candidate reports. Individual accounts describe a particular role and hiring cycle.
Docusign Account Executive interview with multiple presentations
I went through an Account Executive hiring process that felt average to difficult. It dragged on for months, with several rounds, shifting timelines, and a lot of work for the candidate. The early recruiter conversations seemed promising. I then had additional interviews with hiring managers, followed by separate presentations that I had to prepare and deliver. Those presentations took substantia…
Read full experienceDocusign Account Executive interview focused on a predefined career path
I went through an Account Executive process where the hardest part was the team's consistent focus on specific career-path assumptions and alignment with its sales narrative. In the recruiter screen, I discussed my background and career goals, but the recruiter's expectations were closely tied to a predefined SDR to MDR to AE storyline. In later conversations with managers and leads, I discussed…
Read full experienceAccount Executive interview at Docusign: Post-interview feedback
I had a short, professional interview experience for an Account Executive-related role. It felt easy and respectful, with clear communication and feedback after the interview. I first spoke with HR in a professional online conversation. Then I had a role discussion with an interviewer who was welcoming and set a good tone for the process. Afterward, even though I didn't get the offer, I received…
Read full experienceDocusign Software Engineer interview: API script and HackerRank-style exercises
My process was shorter and heavily front-loaded. It began with a quick recruiter screen, then moved into a panel-style technical evaluation. The questions covered coding and system design, and nothing felt wildly unexpected. They were standard areas they wanted to see me handle calmly. The process continued in a way that felt somewhat drawn out but still organized. I had four interviews in total,…
Read full experienceDocusign Software Engineer interview: hour-long whole-team coding rounds
I had a team-manager kickoff and then moved into a whole-team round with several people interviewing me back-to-back. The scheduling details suggested that each team member would take about 30 minutes, but in practice each conversation lasted closer to an hour. That changed the pacing of the day. The technical conversations focused mainly on coding. Because they ran long, I had fewer natural brea…
Read full experiencePracHub editorial advice for the preparation topics above.
Solving the JSON-parsing or API-call prompt for the happy path only, with no edge cases or error handling
Before you write code, list the inputs out loud. For parsing: empty input, invalid JSON, nested objects and arrays, missing keys, wrong value types, very large numbers, and escaped characters. For the API call: 2xx versus 4xx versus 5xx, timeouts, 429 with a retry delay, retries only on retryable statuses with capped backoff, and no blind retries of writes that are not idempotent. Say which cases you handle in code now and which you would add with more time. The notes list modular code with proper error handling under code quality.
Coding in silence and explaining complexity only when asked
One reported question is to explain the time and space complexity of the code you just wrote, so treat that explanation as part of every answer. State your approach and target complexity before you type, and explain decisions as you make them. Finish with time and space bounds that include hidden costs such as string concatenation in a loop, recursion stack depth, sorting, or copying input. Practise saying these out loud, because being correct but silent looks like guessing.
Presenting a URL shortener or multi-region design as boxes with no schema, no database trade-off and no consistency decision
The reported design prompts ask directly about database trade-offs and about consistency versus availability, so answer those questions explicitly. Give the API, the schema (short code, long URL, owner, created_at), and the ID generation choice (a counter encoded in base62, or a hash with collision handling). Then cover the cached read path, and where writes go across regions: one writer region, or several with conflict handling. Say which reads may be stale and for how long, and what each choice costs you.
Freezing when the interviewer moves from an algorithm to system design or a project deep dive
Candidates report this switch, so plan for it. Know one recent project in detail: its architecture, why you chose each technology, and one trade-off you would revisit. Have a sentence ready that moves you from code to architecture. If the new scope is unclear, ask which part they want to go deeper on. The notes suggest the same move for unstated requirements: ask whether there are specific constraints or edge cases you should consider. Rehearse with a partner who interrupts without warning.
Giving a generic why-Docusign answer and telling team stories in the plural
Why Docusign is a reported question. Tie your answer to work you have done that overlaps with the role, such as API integrations, document or workflow systems, front-end performance, or systems where correctness and security matter, and say what you want to do next. In every behavioral story, name the part you did and who did the rest. The notes point behavioral answers at individual contribution and business impact, and a story that stays plural under a direct follow-up reads as someone else's work.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Implement a solution for a string manipulation problem.
Implement a solution for a string manipulation problem.
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
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
How would you handle asynchronous programming in a distributed system?
How would you handle asynchronous programming in a distributed system?
Approach
- Walk one small example through your approach before writing the whole thing.
- 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
- What is the worst case, and how likely is it on real data?
- Which test case would catch an off-by-one here?
Explain the time and space complexity of the code you just wrote.
Explain the time and space complexity of the code you just wrote.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Choose the data structure from the access pattern, not from familiarity.
- 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?
Write a function to parse a JSON object and handle potential edge case…
Write a function to parse a JSON object and handle potential edge cases.
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
- What is the worst case, and how likely is it on real data?
- Which test case would catch an off-by-one here?
Fold a deduplicated usage stream into hourly rollups
You are given one day of usage_event rows, up to 250 million, each carrying event_id, tenant_id, workspace_id, environment, sku, quantity numeric(20,6), idempotency_key, occurred_at and ingested_at. Produce usage_rollup_hourly cells keyed (tenant_id, workspace_id, sku, hour_start) with quantity_sum, event_count and source_max_ingested_at. An event counts once per (tenant_id, idempotency_key). The rollup grain has no environment column, so state your filter. One pass. Give your time and space bounds, and say what the deduplication actually costs in memory.
Approach
- Bucket on
occurred_at, neveringested_at:hour_start = date_trunc('hour', occurred_at at time zone 'UTC'). The two columns answer different questions.occurred_atsays which hour the customer is billed for;ingested_atsays how current the fold is. Using the second for the first makes late data invisible instead of correctable. - The fold is trivial and the deduplication is the entire cost, so price it before designing anything clever. An exact set over
(tenant_id, idempotency_key)at 250M entries, stored as a 16-byte 128-bit hash in an open-addressed table at 0.7 load factor, needs about 357M slots at 16 bytes each, roughly 5.7 GB. The fix is partitioning byhash(tenant_id) % Pso each shard holds 1/P of the set and no tenant's keys straddle shards. - Rule out a Bloom filter as a replacement, in the right direction: a false positive reports 'already seen' for an event never seen, so you drop a real event and lose revenue with no error raised. It is usable only as a negative pre-filter in front of the exact set, where a miss is conclusive and a hit must fall through to the real lookup.
- Accumulate in scaled integers, not binary floating point.
numeric(20,6)admits values below 10^14, so one event scaled to micro-units can reach 10^20, past int64's 9.22 x 10^18; use a 128-bit or arbitrary-precision accumulator unless you first bound the per-event maximum. binary64 represents integers exactly only to 2^53, about 9.01 x 10^15, and cannot represent 0.1 at all, so two runs that sum in different orders disagree. - Carry
source_max_ingested_at = max(ingested_at)over the events folded into each cell, and countevent_countover accepted, post-dedup events. Without that watermark there is no way to prove later what a number did and did not include, which is the first question any reconciliation asks. - State the environment filter explicitly, because the rollup grain cannot record it. A fold that quietly includes
stagingbills non-production traffic; one that quietly excludes it loses a cost signal. Production-only is the billing answer, and either way it belongs in the job name and the output metadata. Complexity: O(n) time, O(distinct dedup keys) space, dominated by the dedup set rather than by the cells.
Worked solution 25 min
- Write both key tuples down before any code: dedup key
(tenant_id, idempotency_key), cell key(tenant_id, workspace_id, sku, hour_start), withhour_startderived fromoccurred_atin UTC. - Build a 10,000-row fixture containing one event duplicated three times under the same
idempotency_key, two events sharing anidempotency_keyacross differenttenant_idvalues, one event whoseoccurred_atis two hours before itsingested_at, and onestagingevent inside an otherwise production cell. - Fold it and assert each of those four expectations separately rather than eyeballing a grand total.
- Re-run with the input shuffled and diff the output files.
- Size the dedup set for 250M keys using the load-factor arithmetic and write the number down next to the fixture.
Follow-up
- A producer retries at 23:59:59 and the retry lands at 00:00:01. The unique index on the daily-partitioned table must include the partition key. What gets double-counted, and what is the smallest change that fixes it?
- The consumer acknowledges its batch before committing the fold. Which failure loses revenue now, and which arrangement duplicates instead?
- What makes a re-run over the same day produce byte-identical rollups?
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.
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?
Migrate a live partitioned event table without blocking ingest
usage_event is range-partitioned daily on ingested_at, holds roughly 250M rows per day across 400 live partitions, and is written at 10-40k rows/second. Two changes are required: quantity must move from double precision to numeric(20,6), and a new environment column must become NOT NULL with a default of 'production'. Ingest cannot stop. Give the ordered plan, naming for each step the lock it takes, what that lock blocks, and roughly how long it is held. Identify the one step that cannot be rolled back cleanly once traffic depends on it.
Approach
- Classify the two changes before planning anything. Adding a column with a non-volatile default has been metadata-only since PostgreSQL 11, so it is cheap. Changing double precision to numeric is not binary-coercible, so
alter column ... typerewrites every partition under ACCESS EXCLUSIVE and rebuilds its indexes; on this volume that is hours of blocked ingest and is simply not an option, which is why the plan is expand-and-contract rather than one statement. - Expand: add
quantity_numeric numeric(20,6)andenvironmentwith its default on the parent. Both are catalogue-only but both take a brief ACCESS EXCLUSIVE that cascades to partitions, so run each withlock_timeoutset to a second or two and retry on failure. A queued ACCESS EXCLUSIVE request blocks every reader behind it, which is how a metadata-only change turns into an outage. - Dual-write: deploy producer code that populates both columns on every insert, and leave it running before anything reads the new column. This is the step that cannot be reverted cleanly. Once readers depend on quantity_numeric, reverting the writer leaves rows with a null there, and the gap is only discoverable by re-reading the old column, which the readers have stopped doing.
- Backfill older partitions in batches keyed on the primary key, oldest first, committing every few thousand rows with a pause between batches, and skipping the partition still receiving writes until it rotates. Each batch is an ordinary UPDATE taking row locks only. The cost is bloat and WAL rather than blocking, so watch dead tuples and let autovacuum keep pace instead of wrapping 400 partitions in one transaction.
- Make NOT NULL cheap with the three-step form:
add constraint ... check (environment is not null) not valid(brief ACCESS EXCLUSIVE, no scan), thenvalidate constraint(SHARE UPDATE EXCLUSIVE, scans while reads and writes continue), thenset not null, which from PostgreSQL 12 uses the validated check and skips its own full scan. Do this per partition, then on the parent. - Switch and contract: move reads to the new column behind a flag, verify over a full period that both columns agree on freshly written rows, drop the old column (metadata-only), and only then remove the dual-write. Any index on the new column goes on with CREATE INDEX CONCURRENTLY per partition, since CIC is not supported on a partitioned parent: create the parent index with ONLY, build each child concurrently, then ALTER INDEX ... ATTACH PARTITION until the parent index becomes valid.
Worked solution 45 min
- On a scratch cluster, build 10 partitions of 2M rows each and run a writer at a few thousand inserts/second.
- Run the naive type change and measure how long writes stall and how far ingest lag grows before killing it.
- Run the expand step with
lock_timeout = '2s'while the writer runs, and observe a clean lock timeout and retry instead of a pile-up of blocked readers. - Backfill in 5k-row batches and chart dead tuples and WAL generated per batch.
- Run the not-valid, validate, set-not-null sequence and confirm from
pg_stat_activityand timings that nothing held an exclusive lock through a full scan. - Add an index with CIC per partition plus ATTACH PARTITION and confirm the parent index reports valid only after the last attach.
Follow-up
- A CREATE INDEX CONCURRENTLY fails halfway through the partition list. What state is the table in, how do you detect it, and what do you run?
- The producer computes quantity itself. What happens to a request already in flight when the dual-write deploy lands, and does it matter?
- Give two queries that prove the backfill is complete: one cheap enough to run every minute, one authoritative.
How do you ensure consistency and availability in a distributed enviro…
How do you ensure consistency and availability in a distributed environment?
Approach
- 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.
- Name the failure you are designing for, then the recovery path.
Follow-up
- What would you drop to keep the system up under load?
- How does this behave when that dependency is down for an hour?
Explain how you would design a system to handle large amounts of data.
Explain how you would design a system to handle large amounts of data.
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.
- Choose a partition key and say what query it makes expensive.
Follow-up
- How does this behave when that dependency is down for an hour?
- What breaks first when traffic grows ten times?
Leasing sandboxed job runs without double execution
job-runner leases work from a queue and executes customer workloads in sandboxes with CPU, memory, wall-clock and egress limits. Run durations span 200 ms to 30 minutes, thousands are concurrent, and job_run.status must reach exactly one terminal state among succeeded, failed, timed_out, cancelled and lost. A worker can pause 45 seconds for garbage collection, or be briefly partitioned, after its sandbox has exited but before it writes the outcome. Design the lease duration, the fencing, and timeout ownership, and state how billable_seconds is computed for a run whose worker never returns.
Approach
- Resolve the lease-duration conflict rather than picking a compromise. A lease shorter than the longest legitimate run re-dispatches work that is still executing; a lease long enough for a 30-minute run leaves a crashed 200 ms run undetected for half an hour. Use a short lease - about 30 seconds - renewed by a heartbeat every 10 seconds while the supervisor is alive, each renewal pushing leased_until to now() + 30 s. Detection latency is then one lease, not one heartbeat: a dead worker's last successful heartbeat landed at most 10 s before it died, so leased_until expires 20 to 30 s after the death, plus whatever interval the reaper scans on. What the 3:1 ratio of lease to heartbeat buys is headroom - one or two missed heartbeats change nothing, and a stall only becomes a re-dispatch once it outlives the lease remaining when it began, between 20 and 30 s here. Both costs follow from those two numbers: heartbeat write load proportional to concurrent runs (3,000 runs at a 10-second interval is about 300 updates/second), and any pause longer than the lease - the 45-second GC - re-dispatching a run that is perfectly healthy.
- Fence the outcome write so the store, not the worker's memory, arbitrates: UPDATE job_run SET status = $1, finished_at = $2, exit_code = $3 WHERE run_id = $4 AND status = 'running' AND lease_token = $5, and require exactly one row affected. Zero rows means this worker was fenced while it was paused, and its correct behaviour is to discard the result, not to retry - the retry is how a resumed worker overwrites a newer attempt.
- Make the status machine monotone with a check constraint or a trigger so no terminal row can move, and model a retry as a new row with parent_run_id set and attempt incremented rather than a reset of the old one. That is what keeps how many times did this actually execute answerable afterwards and keeps each attempt's resource usage attributable to itself.
- Put the wall-clock timeout in the supervisor, never in the workload: a customer-supplied program asked to time itself out will not. Distinguish timed_out, which the supervisor observed and caused, from lost, which nobody observed at all, and leave exit_code null unless the supervisor actually saw the process exit. Recording lost as failed asserts an outcome no one witnessed and then bills and retries on that assertion.
- Decide billable_seconds for the unobserved case explicitly, because it cannot be derived. It is not now() - started_at, which bills queue and pause time the customer never consumed. The two defensible policies are leaving it null while status = 'lost' and billing nothing, or flooring it at the last heartbeat's observed running time as a stated lower bound; pick one and write it down. Add a per-tenant concurrency cap on sandbox slots so one tenant cannot occupy the whole fleet while these questions are being answered.
Worked solution 30 min
- Draw the timeline: last successful heartbeat at t, sandbox exits at t, worker pauses from t to t+45 s, so leased_until = t+30 s and the lease expires there. Mark where the second worker starts and where the first worker's write arrives, then say how short the pause would have had to be to change nothing.
- Write the fenced terminal update and state the expected rows-affected in both the healthy case and the fenced case.
- Size the heartbeat: 3,000 concurrent runs at a 10-second interval is about 300 row updates/second on job_run - decide whether that lands on the same table and what it contends with.
- Write the billable_seconds rule for each terminal status and say which status leaves it null.
Follow-up
- A worker returns from a 45-second GC pause and writes succeeded. Walk through what the database does statement by statement.
- Heartbeats are now a few hundred writes a second against job_run. How do you keep that off the path that matters, and what do you lose by moving it?
- The re-dispatched workload has an external side effect the first attempt already performed. What does your design owe the customer, and what can it not fix?
Invoice detail latency triples after an ORM relationship refactor
An invoice detail endpoint returned in 40 ms at p99 last week. After a refactor replaced a hand-written join with ORM relationship access it returns in 1.4 s, and the regression grows with the number of invoice_line_item rows on the invoice. Database CPU rose, but no statement in the slow-query log exceeds 3 ms. You have request traces with per-span SQL, the ORM statement log, and a staging copy of the data. Produce an ordered diagnostic checklist, the measurement that confirms the cause before any code change, and the fix.
Approach
- Count statements per request before reading any statement duration. A slow-query log hides this class by construction, because every individual query is fast and only their number is wrong; take one trace and count SQL spans.
- Establish proportionality rather than asserting it: sample invoices with 5, 20, 60 and 200 line items and plot statements per request against line count. A straight line of slope 1 through an intercept of one or two identifies a lazy relationship load, and no index or cache would move that line.
- Locate the emitting attribute access in the refactored code and check whether the same shape repeats one level deeper, for instance a tax or adjustment collection hanging off each line, which turns the cost quadratic.
- Fix with a bounded statement count: either one join that fetches invoice and lines together, or two statements where the second is WHERE invoice_id = $1 AND tenant_id = $2. Keep tenant_id in the predicate so the read stays tenant-scoped even though invoice_id already implies it.
- Choose between the two deliberately: the join duplicates the wide parent row across N children on the wire, the two-statement form avoids that for one extra round trip. Prefer the join for narrow parents and the split for wide ones.
- Pin it with a per-request statement-count assertion in a test that varies line count, because a latency assertion passes on a small fixture and would not have caught this.
Follow-up
- The endpoint now also needs per-line tax rows. Show the shape that keeps statement count constant instead of reintroducing the same defect one level down.
- How does this change if a transaction-pooling proxy sits between the service and the database, so each statement may land on a different backend session?
- The same page paginates invoices with LIMIT and OFFSET. Why is that a second, independent defect, and what replaces it?
For someone who has spent the last few years shipping features and reading other people's code, and who has not solved a timed problem from a blank file in a long time. Five days rebuild the primitives and the patterns that sit on them, working from invariants rather than remembered solutions, and the last two attach that back to the rest of the loop.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Recruiter screen: posting map, why Docusign, one project
- Mark every line of the posting as done, adjacent or new, and check it against the must-haves in the notes: one modern language, data structures and algorithms, and API development with RESTful services
- Write a two-sentence why-Docusign answer tied to your own work, and say it aloud until it no longer sounds memorised
- List your screen questions: team, languages and frameworks, whether system design is in the loop at your level, and whether full-stack means designing the UI and the API in one interview
- Choose the project you will use for deep dives, and write down its architecture, two choices you would defend, and one you would change
Deliverable: A posting map, a why-Docusign answer, a recruiter question list, and a one-page project brief.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Coding: strings and JSON parsing with edge cases
- Solve Compress Consecutive Integer Ranges from the bank and one string manipulation problem, stating the approach and complexity before writing code
- Write a function that parses a JSON object and handles edge cases: empty or malformed input, nested arrays and objects, missing keys and wrong types. Before you start, ask whether a standard-library parser is allowed or a hand-written one is expected
- Outline the bank's Design a JSON Schema Validator: supported types, required fields, and error messages that report the nested path
- Write the test list before each solution, then run it and note every case you missed
Deliverable: Three solutions, each with a test list written in advance and a spoken complexity statement.
Practice prompt ↗Practice prompt ↗03Coding: hash maps, heaps, grids, and complexity out loud
- Solve Top K Frequent Elements three ways (full sort, size-k heap, bucket counts) and state the time and space for each
- Solve Find maximum island sum and required indices with BFS or DFS over the grid, and note the recursion-depth risk for large grids
- Implement a key-value CRUD store: define the API, the behaviour on a missing key, and the complexity of each operation
- Work the drill 'Fold a deduplicated usage stream into hourly rollups' with its worked exercise, and practise explaining where the memory goes, as the reported complexity question asks
Deliverable: Four solutions, each with a recorded spoken explanation of time and space complexity.
Practice prompt ↗Practice prompt ↗04Coding: API calls, async work and failure handling
- Write a script that calls an HTTP API and handles 200, 204, 400, 404, 429 and 5xx responses plus timeouts, with retries only where the request is safe to repeat
- Prepare an answer to 'How would you handle asynchronous programming in a distributed system?' covering queues, at-least-once delivery, idempotency keys, timeouts, retries and a dead-letter path, with one concrete example
- Work the design drill 'Leasing sandboxed job runs without double execution' with its worked exercise, focusing on why a lease alone does not stop a stale write
- Do the debugging drill 'Invoice detail latency triples after an ORM relationship refactor', counting statements per request before reading any durations
Deliverable: An API-call helper with a status-handling table and a one-page answer on async work across services.
Practice prompt ↗Practice prompt ↗Worked solution ↗05System design: URL shortener, multi-region, database trade-offs
- Design a URL shortener for high traffic end to end: API, schema, ID generation, cached read path, and what breaks first at ten times the traffic
- Extend it to multiple regions: where writes go, which reads may be stale, how failover works, and your explicit consistency-versus-availability decision
- Outline the bank's Design paginated list UI and pagination API, using the drill 'Paginate a tenant's delivery export without skipping rows' for keyset versus offset
- For each design, write one SQL-versus-NoSQL decision tied to the access pattern and what it gives up
Deliverable: Two design sketches, each with a schema and one written database trade-off.
Practice prompt ↗Practice prompt ↗06Large data, SQL fundamentals and object design
- Work the drill 'Migrate a live partitioned event table without blocking ingest' with its worked exercise
- Answer 'design a system to handle large amounts of data': choose a partition key, name the query it makes expensive, and decide between batch and stream processing
- Outline the bank's Design a multi-level parking system: classes, spot allocation, and what happens when two cars claim the same spot
- Review foreign keys and the request flow from browser to server, the topics of the bank question Foreign Key and URL Behavior
Deliverable: A large-data design note and a class outline for the parking system.
Practice prompt ↗Practice prompt ↗07Behavioral stories and a mixed mock
- Write STAR stories for the five reported prompts: a disagreement with a peer, a challenging project you led, ambiguous requirements, mentoring, and why Docusign
- Use the drill 'Unblock an engineer on a job run that finished twice' as a model for the mentoring story, and name what the other person could do afterwards without you
- Run a mock with a partner: one coding problem, a switch without warning to system design or your project deep dive, then two behavioral prompts
- Re-solve your slowest problem of the week from a blank file and compare it with your first attempt
Deliverable: Five STAR stories and written notes from the mixed mock, including where the switch between levels went badly.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Candidates describe these as conversations with hiring managers and peer engineers about fit and collaboration. The notes advise STAR answers that focus on your own contribution and its impact on the business. Build one story per reported prompt, and make each one hold up through follow-ups: the constraint that ruled out the obvious option, the part you did yourself, and a result you can state accurately.
Tell me about a time you had a technical disagreement with a peer; how…
Tell me about a time you had a technical disagreement with a peer; how did you resolve it?
Approach
- Close with what you would do differently, concretely.
- Give the blast radius: what could have broken, and what you measured.
- State the situation in two sentences and spend the rest on the reasoning.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Why are you interested in Docusign specifically compared to other tech…
Why are you interested in Docusign specifically compared to other tech companies?
Approach
- Give the blast radius: what could have broken, and what you measured.
- State the situation in two sentences and spend the rest on the reasoning.
- Pick a story where you made the decision, not one where you watched it.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Unblock an engineer on a job run that finished twice
An engineer two weeks into the team brings you a job_run row showing status succeeded with an exit_code written by a worker declared dead ten minutes earlier; the retry attempt also shows succeeded. They have spent a day adding logging and are no closer. You have twenty minutes and you do not want to take the keyboard. Describe how you unblock someone: the question you ask first, what you let them find themselves, the concept you name and when, and how you check the next day that they own the fix rather than having watched you produce it.
Approach
- Ask what they expect rather than what they see: which statement set status to succeeded, and what did it check before writing? That question points directly at the update's WHERE clause, which is where the answer lives, and it costs them nothing to answer, so it does not read as a test.
- Let them build the timeline themselves from the row: queued_at, started_at, leased_until, finished_at and worker_id, on both the original run and the retry. Two different worker_ids with a lease expiry between them tells the whole story, and they will see it before you say it.
- Name the concept once the evidence has earned it. A lease bounds time; it does not prevent a write. The store has to reject a stale writer, which means the update carries a fencing token the row compares — update job_run set status = 'succeeded' where run_id = $1 and lease_token = $2 and status = 'running' — and a long garbage-collection pause or a brief partition is enough to produce what they are looking at.
- Point at the second, less obvious half and let them decide it: 'lost' exists in the status enum precisely so a run whose worker vanished is not recorded as failed, because failed asserts an outcome nobody observed and the system then bills and retries on that assertion. Ask them what these two rows should have said.
- Leave them with the next step rather than the patch — a test that kills the first worker after the sandbox exits and before the row is written — and say when you are available again, so the offer is real rather than polite.
- Check ownership the next day by what they produced, not by asking if it went well: a test that reproduces the window proves they understood it; a test that only asserts the new WHERE clause proves they copied it. Ask them to explain it to a third person and listen for whether the explanation is theirs.
Follow-up
- They propose a longer lease instead of a token. What do you say, and what breaks when legitimate runs last thirty minutes?
- How can you tell whether your explanation landed or they simply deferred to you?
- The same engineer hits a variant of this next month. What did you fail to teach the first time?
- 01
Tell me about a time you had a technical disagreement with a peer; how did you resolve it?
- 02
Describe a challenging project you led and the impact it had on the business.
- 03
How do you handle situations where you are given ambiguous requirements?
- 04
Describe a time you had to mentor a junior engineer or help a teammate.
- 05
Why are you interested in Docusign specifically compared to other tech companies?
Is this an official Docusign interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Docusign. The rounds and questions reflect what candidates have reported, not a process Docusign 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?
Candidate reports in the source notes put coding questions at easy to medium on standard practice platforms. They focus less on trick questions and more on how clearly you explain your thinking. The reported prompts are practical: parsing JSON with edge cases, string manipulation, an API call with response-status handling, and explaining the complexity of your own code. Practise those alongside standard algorithm work on arrays, strings, trees, graphs, hash tables and heaps.
PracHub interview research ↗Will there be a system design interview?
The notes describe the technical rounds as a mix of coding assessments and system design discussions. Ask your recruiter what to expect at your level. For preparation, the reported design questions are a URL shortener for high traffic, a multi-region low-latency system, a system for large amounts of data, database trade-offs, and consistency versus availability.
PracHub Software Engineer practice ↗Which programming language should I use?
Use the language you are strongest in. The notes mention React for front-end teams and Java, Python or TypeScript for back-end teams, and they say to be ready to explain how your language and frameworks work under the hood, not only how you use them. For a full-stack seat, be ready to talk about both client-side performance and back-end scalability, and possibly to design a UI component and its API in the same interview.
PracHub Software Engineer practice ↗How should I handle an interviewer who seems disengaged?
Stay professional and keep working on the technical problem. If the interview seems to stall, ask a clarifying question to bring the conversation back to the task, such as whether there are specific constraints or edge cases you should consider. That question also protects you when the interviewer has a requirement in mind that they have not stated.
PracHub interview research ↗How do I prepare for a project deep dive?
Choose one recent, complex project and learn it in detail: the architecture, why you picked each technology, the trade-offs you accepted, and what you would do differently if you built it again today. Candidates report interviewers switching to a deep dive in the middle of a technical round, so prepare it alongside your coding practice and do not leave it for the behavioral stage.
PracHub interview research ↗What is the 'tech quiz' some candidates mention?
The notes say some rounds may include rapid-fire questions about frameworks or CS concepts. Answer what you know briefly and say plainly when you do not know something. Review your main language's internals, asynchronous programming patterns, REST and HTTP status semantics, and basic database concepts such as foreign keys and indexing.
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