As a Software Engineer at the National Payment Corporation of India, you are at the heart of the nation’s digital financial infrastructure. This role is not merely about writing code; it is about building, maintaining, and scaling the systems that facilitate millions of daily transactions, ensuring that India’s payment ecosystem remains secure, resilient, and highly efficient. You will contribute to mission-critical platforms that touch the lives of millions, requiring a balance of high-performance technical execution and a deep understanding of transactional integrity.
The work environment is fast-paced and demands a high degree of precision. You will collaborate with cross-functional teams, including product managers, security experts, and infrastructure engineers, to solve complex challenges related to high-concurrency systems and real-time data processing. Success in this role requires a candidate who is not only technically proficient but also deeply committed to the reliability and security of financial services. Whether you are optimizing existing payment gateways or building new features for digital payment products, your contributions will have a direct impact on the country's economic connectivity.
Phone Screening
reportedBefore anything technical happens, someone has to decide which rung of the ladder your loop is calibrated to, and that decision sets the bar for every round after it. It comes from how you describe scope, not from your title, because titles do not convert cleanly between companies. The weak version of the answer is team size and years. The strong version names the largest change you shipped where nobody reviewed the design, what would have broken if you had been wrong, and what you were paged for. Get the level said out loud on this call, because the range and the loop both follow from it.
What to demonstrate
- Whether the scope in your own account maps onto a level the team actually has an opening at, so a mismatch ends the process cheaply rather than after four interviewers have spent a day
- Whether your title needs re-mapping: the same word describes very different amounts of independent decision-making at a twenty-person company and a ten-thousand-person one
- Whether your compensation expectation can be filled at that level in the structure the role pays in, which is why the number gets asked for before any engineer is scheduled
How to prepare
- Write down two changes from the last two years: the largest one you designed with nobody reviewing the design, and the largest one where someone more senior did. Lead with the first when scope comes up, and be ready to say which parts of the second were yours
- Ask which level the loop is calibrated to and what changes at the level above it, then plan your weeks from that answer rather than from the posting
- Settle a total-compensation range beforehand with the split named, base against bonus against equity and its vesting period, so a question about numbers gets a number instead of the word market
Technical Deep-Dive
reportedInput bounds are the part of the prompt most often skimmed, and they usually contain the answer. They tell you which complexity class is admissible, which narrows the search before you have thought about the problem itself. As a rough planning figure, a compiled language does on the order of 10^8 simple operations per second and an interpreted one roughly an order of magnitude less. So n up to about twenty admits enumerating subsets, a few thousand admits a quadratic pass, and a million admits neither: you need near-linear, or linear with a log factor. If the bounds are missing, ask for them.
What to demonstrate
- Whether the approach is justified by the stated input size rather than by whichever pattern you recognised first
- Whether you ask about the properties that change the algorithm: whether the input arrives sorted, whether duplicates occur, whether values are bounded integers, whether it all fits in memory
- Whether you can name the bottleneck in your own solution and what would remove it, even when you deliberately leave it in place
- Whether a claimed speedup is real, since memoising a recursion only helps when subproblems genuinely overlap and the state can be keyed cheaply
How to prepare
- For each algorithm you rely on, write down the largest n it handles in roughly a second, then check two of those figures by timing them in the language you will actually type in
- For two weeks, write one line naming your target complexity and the bound that justifies it before you write any code, then compare that line with what you ended up submitting
- Practise the conversion backwards: given a required O(n log n), list the mechanisms that get you there (sorting, a heap, an ordered map, divide and conquer) and choose by what the problem needs to query, not by what you used last
PracHub editorial advice for the preparation topics above.
Treating money as a decimal with two places
ISO 4217 exponents are 0 for currencies such as JPY and KRW, 2 for most, and 3 for BHD, KWD, JOD, OMR and TND, so a hard-coded multiply-by-100 is off by a factor of 100 or 10 depending on the currency, in opposite directions. Floating point is worse: IEEE 754 binary64 cannot represent 0.1 exactly, so repeated accrual accumulates drift that appears as a handful of minor units in the daily reconciliation and then gets 'fixed' by widening the match tolerance, which is how a genuine break becomes invisible. The only forms that survive a reconciliation are integer minor units with the exponent carried alongside the currency code, or a fixed-scale decimal type with exactly one documented rounding point.
Writing the state change to the database and publishing the event in the same code path
No transaction spans a relational database and a message broker, so a crash between the two leaves one done and the other not, and the failure is asymmetric in both orderings: publish-then-commit invents events for state that never existed, while commit-then-publish silently loses events for state that does. Retrying the publish after the commit is not a fix, because the process can die before the retry runs. The working shape is an outbox row written inside the same transaction plus a relay that publishes it at least once, which makes consumer-side idempotency mandatory rather than optional. Note also that 'exactly-once' in a stream processor means exactly-once processing within that system's own read-process-write transaction, and says nothing at all about an external side effect such as charging a card.
Naming no test cases at all
State what you would test before being asked: empty input, a single element, all elements equal, the maximum permitted size, and the input that exercises the branch you just wrote. It costs thirty seconds and is much of what separates someone who has shipped code from someone who has only solved puzzles.
Starting work without saying what you are about to spend time on
State the plan before executing it: the approach, roughly how long it will take, and what you intend to leave hand-waved. That gives the interviewer a chance to redirect you in ten seconds rather than watching you spend fifteen minutes on the wrong sub-problem.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
What is your approach to debugging issues in distributed environments?
What is your approach to debugging issues in distributed environments?
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- 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?
- What is the worst case, and how likely is it on real data?
Discuss a project where you had to work with limited resources or tigh…
Discuss a project where you had to work with limited resources or tight deadlines.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
- 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?
Walk us through a complex project on your resume; what was your specif…
Walk us through a complex project on your resume; what was your specific contribution?
Approach
- Walk one small example through your approach before writing the whole thing.
- State the target complexity and say which constraint rules the naive version out.
- 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?
- What is the worst case, and how likely is it on real data?
How do you balance feature performance with system scalability?
How do you balance feature performance with system scalability?
Approach
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
- Walk one small example through your approach before writing the whole thing.
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?
Resolve party identity across merges without rewriting posted history
Duplicate parties get merged over time: a stream of up to 5 million (loser_party_id, winner_party_id, merged_at) events, deliverable in any order, sometimes repeating a pair already merged. Ten million account rows and hundreds of millions of ledger_entry rows already reference pre-merge party ids and must not be rewritten. Build the structure that answers 'what is the canonical party for this id?' in near-constant time, and explain how a report that groups by party stays correct without touching a single historical row.
Approach
- The merge events form an undirected graph over party ids and the question is connected components, so use disjoint-set union with union by size and path compression:
findandunionamortise to O(alpha(n)), and alpha(n) is at most 4 for any n that exists. Five million merges over ten million ids is two integer arrays and a few hundred milliseconds. - The domain twist: the representative cannot be whichever root union-by-size happens to pick, because the canonical party is a business decision recorded as
winner_party_id. Keep union by size for the tree shape and a separateroot -> canonical_party_idmap for the label. Conflating them makes the canonical id flip when an unrelated merge reshapes the tree, and every report built on it moves retroactively. - Never rewrite
ledger_entryoraccount. Resolve at read through the canonical map: rewriting posted rows destroys the audit trail, locks hundreds of millions of rows, and buys nothing the map does not already give you. - Materialise the map fully expanded as
party_id -> canonical_party_id, one row per member rather than per edge, so a report is a single join instead of a recursive traversal. Rebuild it from the event log, which keeps it a derived artefact that can be regenerated rather than a second source of truth that drifts. - Pin down determinism: a repeated merge is a no-op because both ids already share a root, but two events merging the same pair in opposite directions is a genuine conflict. Write the tiebreak down — lowest
merged_at, then lowest id — or two replays of the same log produce different labels for the same data. - Un-merges: disjoint-set union has no delete. If a merge can be reversed, keep the event log authoritative and rebuild the whole structure from the surviving events; at 5 million events that is seconds, and far cheaper than any incremental un-union scheme.
Worked solution 25 min
- Implement disjoint-set union with
parentandsizearrays plus aroot -> canonicalmap, keepingfinditerative with path halving so a ten-million-element chain cannot exhaust the stack. - Apply events sorted by
(merged_at, loser_party_id), setting the new root's canonical label to that event'swinner_party_id. - Fixture: A into B, C into D, B into D applied in that order, plus a repeat of A into B and a self-merge of B into B.
- Expand to the flat map and assert all of A, B, C and D resolve to the same canonical id.
- Shuffle the event order, re-run, and assert the flat map is identical — this is the test that catches an order-dependent canonical label.
Follow-up
- A merge is reversed after six months of postings. What exactly gets rebuilt, and what does the statement produced last month now say?
- Two processes apply merge events concurrently. What guarantees they converge on an identical canonical map?
- Resolving at read on the hot path versus materialising the map — where does that join actually live, and what does each cost?
Decide whether balance is derived or materialised, then hold the floor
Authorisation needs an account's available balance inside an 80 ms budget at 3,000 requests per second; that account already has 200 million ledger_entry rows. A product rule says the balance may never fall below the account's negative overdraft limit. Decide whether the balance is summed from entries or held in a materialised account_balance(account_id, balance_minor, floor_minor, currency, version) row, and justify the choice from the read pattern. Then give the write path that holds the floor, naming the isolation level, the anomaly a weaker level permits, and the SQLSTATE you retry.
Approach
- Size the derived read before arguing about it: summing 200 million rows is not an 80 ms operation under any index, since even a covering index on (account_id, entry_id) still reads work proportional to the rows. The authorisation read pattern forces one materialised row fetched by primary key; the statement read pattern, which is low-rate and historical, stays derived from entries. That is the whole justification for the denormalisation, and its price is a write on that row per posting.
- Put the floor where it can be a single-row constraint: CHECK (balance_minor >= floor_minor) on account_balance, updated in the same transaction as the entries. As a predicate over a set of entry rows it cannot be a CHECK at all, which is the reason the materialised row earns its keep twice.
- Write the mutation as one statement: UPDATE account_balance SET balance_minor = balance_minor - $1, version = version + 1 WHERE account_id = $2 AND balance_minor - $1 >= floor_minor. Zero rows updated means refused. This is safe even under READ COMMITTED, because the UPDATE re-evaluates its predicate against the locked, post-update version of the row.
- Name the anomaly in the shape that is not safe: SELECT the balance, compute a new value in application code, then UPDATE to that constant. Every statement under READ COMMITTED takes a fresh snapshot, so two concurrent 60-unit withdrawals against 100 both read 100 and both write 40. The row then claims 40 while 120 has actually left, so the true position is -20, below a floor of 0, and the row it is checked against cannot show it. PostgreSQL REPEATABLE READ is snapshot isolation and aborts the loser with SQLSTATE 40001; SERIALIZABLE additionally closes write skew across two rows. Both require a bounded retry with backoff, and InnoDB REPEATABLE READ does not abort at all, so identical code changes behaviour on a different engine.
- For a two-account transfer, acquire the rows in a deterministic order such as ascending account_id; without it, opposing concurrent transfers deadlock and the database kills one with SQLSTATE 40P01. That is a retry, not a correctness failure, but it is a retry somebody has to write.
- Finish on the ceiling: the hot row admits one committed write per lock hold, so at a 2 ms hold it caps near 500 per second regardless of cores. Sharding into N sub-rows multiplies throughput and immediately makes the floor check cross-row again, which then needs the shard sum under SERIALIZABLE or a per-shard reserved allowance.
Worked solution 35 min
- Seed one account with balance_minor = 100 and floor_minor = 0, then run two concurrent 60-unit withdrawals under READ COMMITTED using SELECT-then-UPDATE and record the final balance.
- Replace it with the single-statement conditional UPDATE and re-run the same race, asserting on rows affected rather than on an exception.
- Re-run under SERIALIZABLE with the read-modify-write shape, count the 40001 aborts, and add a retry loop with a fixed attempt cap and jittered backoff.
- Measure committed writes per second against that single row, then write the drift query: sum signed entries per account and compare against balance_minor.
Follow-up
- Shard the balance into eight sub-rows. Write exactly what the floor check now does, and what it costs per authorisation.
- Someone proposes an AFTER INSERT trigger on ledger_entry to maintain the balance. What does that change about ordering, about batch posting, and about failure handling?
- How do you detect that the materialised row has drifted from the entries, how often do you run it, and on which replica?
Store multi-currency amounts and prove each transaction balances
ledger_entry holds entry_id, transaction_id, account_id, direction (debit or credit), amount_minor (bigint, CHECK > 0), currency char(3), source_type, source_id, business_date and posted_at. The service posts in JPY, USD and KWD. Specify the column types for money and the reference table that carries each currency's ISO 4217 minor-unit exponent, and say why that exponent must not be a constant in application code. Then write the query that returns every transaction_id whose entries fail to sum to zero within each currency, ordered by the largest absolute imbalance.
Approach
- State the representation: amount_minor is an integer count of minor units and the scale lives with the currency, not in the column. int4 tops out at 2,147,483,647 minor units, which is about 21.5 million units of a 2-exponent currency, so bigint, and the currency code travels on every row that carries an amount.
- Normalise the scale into currency(code char(3) primary key, exponent smallint, name) and join it only at display and parse boundaries. The exponent is 0 for JPY and KRW, 2 for USD and EUR, 3 for KWD, BHD, JOD, OMR and TND, so a hard-coded divide by 100 is wrong by 100x for JPY and by 10x for KWD, in opposite directions.
- Rule out binary floating point outright: IEEE 754 binary64 cannot represent 0.1, so repeated accrual drifts by a few minor units that later appear as reconciliation breaks. If a fixed-scale decimal is used instead, pin the scale per currency and name the single place rounding happens.
- Write the balance check as a grouped aggregate: sign the amount with a CASE on direction, GROUP BY transaction_id, currency, and HAVING the signed sum <> 0. The sign belongs in direction, and the CASE is the one place it becomes arithmetic.
- Then order in a second layer, because the ordering the question asks for cannot be written on the grouped query itself. PostgreSQL lets an output alias stand alone in ORDER BY but resolves anything inside an expression against the input columns, so ORDER BY abs(imbalance_minor) DESC raises SQLSTATE 42703, column "imbalance_minor" does not exist, while the bare ORDER BY imbalance_minor DESC is accepted and sorts signed rather than absolute. Wrap the grouped query and order by abs() outside it, or repeat the aggregate as ORDER BY abs(SUM(CASE ...)) DESC, which is legal because aggregates are allowed there.
- Group per (transaction_id, currency) rather than per transaction, because a cross-currency movement balances only within each currency, bridged by an explicit FX position account whose rate, source and timestamp are stored on the transaction.
- Note that no CHECK constraint can express this, since it spans rows: enforce it at write time with a DEFERRABLE INITIALLY DEFERRED constraint trigger that fires at commit, or by routing every posting through one function, and keep this query as the independent audit.
Follow-up
- A transaction has a USD leg and a JPY leg. Which accounts appear, and where does the rounding residual land?
- How would you enforce the zero-sum rule at write time without serialising all postings behind one lock?
- Someone proposes storing a display amount alongside amount_minor. What goes wrong at the first rate change or rounding rule change?
How would you explain the life cycle of a transaction within a high-co…
How would you explain the life cycle of a transaction within a high-concurrency system?
Approach
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
- Clarify what is being asked and what a complete answer contains.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Explain the importance of virtual destructors in C++.
Explain the importance of virtual destructors in C++.
Approach
- Say what you would check first and why it is the highest-information step.
- Clarify what is being asked and what a complete answer contains.
- Work from the requirement backwards to the design.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Capture endpoint that survives concurrent duplicate retries
POST /payments/{intent_id}/capture carries an Idempotency-Key header and an amount. Callers retry on timeout, and two retries can land concurrently on different instances. You have idempotency_key(id, scope, key, UNIQUE(scope,key), request_fingerprint bytea, status in_progress|completed|failed, response_status, response_body jsonb, locked_at, completed_at, expires_at). The processor capture takes 200 to 2,000 ms. Design the path so exactly one capture reaches the processor, every duplicate receives the identical response, and a crash between the processor call and your commit converges. Name the single statement that is the concurrency control.
Approach
- The concurrency control is INSERT INTO idempotency_key (...) VALUES (...) ON CONFLICT (scope, key) DO NOTHING RETURNING id, and it must commit before the processor call. A returned row means you own the effect; zero rows means you lost and must read the winner's result. A SELECT-then-INSERT check cannot substitute: two requests both read 'absent' and both proceed, and the window is exactly the concurrency you are defending against.
- Commit the in_progress row in its own short transaction. A concurrent duplicate insert blocks on an in-flight conflicting insert until that transaction ends, so wrapping the 2 s processor call in the same transaction turns every duplicate into a 2 s lock wait and a retry storm into pool exhaustion.
- Define loser behaviour per status rather than uniformly: completed replays response_status and response_body unchanged; in_progress returns 409 with Retry-After and performs nothing; failed splits by cause, since a terminal processor decline should replay but a transport failure should let the key be retried. Getting this wrong in the safe direction (replay a decline) is better than returning an error for a capture that succeeded.
- Fingerprint the canonicalised body with SHA-256 and compare on every hit. Same key with a different amount is a client bug and must return 409 or 422, never the cached response, because returning the cached body silently captures the old amount and looks successful.
- Pass the same key to the processor so deduplication holds end to end, and generate it once at the originating caller. A key regenerated per attempt leaves every line of idempotency code in place while disabling the mechanism entirely.
- Converge after a crash by querying the authoritative side rather than guessing: a reaper picks up rows in_progress past locked_at plus a bound, asks the processor for that key or the intent's processor_reference, and completes the row from the answer. Set expires_at longer than the caller's full retry schedule and document that a replay after expiry is a new request.
Worked solution 30 min
- Implement the endpoint with the ON CONFLICT DO NOTHING insert committed before the processor call, and a processor stub that counts calls and sleeps 1,500 ms.
- Drive 50 concurrent identical requests through two application instances.
- Repeat with the same key and the amount changed by one minor unit.
- Kill the instance between the stub's response and the local commit, restart, and run the reaper.
Follow-up
- The processor does not honour idempotency keys. What is the end-to-end design now, and what can you no longer promise?
- Two merchants send the same key value. What makes that safe?
- You keep keys for 24 hours at 3,000 requests/s. Size the table and the index, and say what expires them.
Approval rate collapses when one feature-store shard fails
The risk decision service answers about 3,000 authorisations per second within an 80 ms p99, reading features from an eight-shard store behind a local cache with a fixed 60-second TTL, a 2-second client timeout and two retries on timeout. One shard becomes unreachable at 14:02. Approval rate falls from 96% to 71% within 90 seconds, and the seven healthy shards show p99 rising to 900 ms with normal error rates. Diagnose in order, name the cause of the approval drop, and state the degraded behaviour this service should have had.
Approach
- Establish what declined actually means here before touching the cache. Split the rate into approve, decline, refer and timeout. If decline counts are flat and timeouts account for the whole 25-point drop, the model is not declining anything; it is failing to answer, and something downstream is reading silence as a decline. That reading is the first finding and the most expensive one.
- Break the store's metrics out per shard. One shard at 100% errors and seven at elevated latency with baseline error rates is the signature of queueing, not of seven shards failing. Healthy dependencies with healthy error rates and bad latency are almost always victims of a shared resource.
- Follow the resource. A single connection or thread pool shared across shards means requests to the dead shard occupy slots for the full 2-second client timeout, which is 25 times the whole p99 budget, and with two retries each such request can hold a slot for 6 seconds. Confirm by comparing pool acquisition wait against per-shard service time: if wait dominates, the pool is the bottleneck.
- Quantify the amplification. Two retries on timeout offer 3x load, and an unjittered 60-second TTL expires a warm set together, so misses arrive as a synchronised wave rather than spread across the window. Retrying a timeout is only correct when the failure is likely transient; against a hard-down shard it is pure amplification and needs a circuit breaker to gate it.
- Fix the three separate defects separately: per-shard pools so one shard cannot starve seven, a breaker that stops retrying a shard that is failing, and per-key TTL jitter with single-flight refresh so N concurrent misses for one key produce one upstream read.
- Write down the degraded decision as a product decision, not a timeout handler's accident. With features unavailable the service must return a stated answer, such as deterministic rules alone below an amount threshold and refer above it, and must record that the decision was degraded so it is auditable and reproducible from stored inputs.
Follow-up
- Approving on deterministic rules alone during a feature outage carries a fraud cost. How do you size the amount threshold, and who signs it off?
- What should the orchestrator do with a risk timeout, given it cannot distinguish one from a decline?
- Does the circuit breaker fix the healthy shards' latency, or is the bulkhead doing that work? Which would you ship first if you could only ship one?
Roughly ninety minutes on weeknights with one longer weekend block. The plan cuts scope rather than compressing everything, on the assumption that one thing finished per night beats four half-started.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Fix the scope and take a cold baseline
- Read the role description and write the three things the loop will almost certainly test, then write an explicit not-doing list and keep it visible all week.
- Take one twenty-five-minute coding problem and one fifteen-minute design prompt cold, and write the single sentence naming what blocked each, because those two sentences decide where the remaining evenings go.
- Set the week's rule: one thing finished every night, including the night you only have forty minutes.
Deliverable: A one-page scope with a not-doing list and two cold attempts, each carrying one sentence on what blocked it.
Practice prompt ↗Practice prompt ↗Worked solution ↗02One pattern, written three times from blank
- Choose the single pattern most likely to appear in your loop and write it three times from an empty file rather than editing the previous attempt.
- On the third pass, write the invariant as a comment before the loop body and the complexity before the first line of code.
- Stop at ninety minutes even if the third version is imperfect, and write the one thing you would fix given another hour.
Deliverable: Three independent implementations of the same pattern plus a note on what changed between them.
Practice prompt ↗Practice prompt ↗03One design, only to the depth you can defend
- Take one system shape and go only as far as requirements, interface and data model, refusing to draw a box you could not survive a follow-up about.
- Attach one number to each non-functional requirement, deriving it rather than asserting it, and write the assumption the number rests on.
- Write the one tradeoff you are choosing against and the observation that would make you reverse it.
Deliverable: One design at interface-and-schema depth with derived numbers and one written reversible tradeoff.
Practice prompt ↗Practice prompt ↗04Only the fundamentals you will have to defend
- Write, in under two hundred words each, the answers to the two questions that follow almost any implementation: why this structure and not the obvious alternative, and what happens to this code at a hundred times the input.
- Write what an index actually costs: faster lookups on the indexed columns against a write that now maintains a second structure, plus the cases where the planner declines to use it anyway, low selectivity, or a predicate wrapping the column in a function.
- Delete any answer you cannot deliver aloud in under a minute, since an answer that needs reading is not an answer you have.
Deliverable: Three written answers, each under two hundred words and each timed aloud.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Your own work, timed
- Write a ninety-second and a four-minute version of your main project and time both aloud rather than reading them.
- Prepare the two follow-ups that always come: what you would do differently, and how you knew it worked.
- Put one number in the first sentence and be ready to say exactly where it came from and what it excludes.
Deliverable: Two timed narratives with one defensible number in the opening line.
Practice prompt ↗Practice prompt ↗06The one full rehearsal, in the weekend block
- Run a sixty-minute mock covering a coding round and a design round in one sitting with no break, because sustained attention is the thing evenings have not trained.
- Immediately afterwards, and before hearing any feedback, write the three moments you lost the thread.
- Spend the rest of the block only on those three moments, and on nothing you merely feel shaky about.
Deliverable: Mock notes naming three failure moments with a specific fix written under each.
Practice prompt ↗Practice prompt ↗07Taper
- Write the twenty-minute warm-up you will actually do on the morning: one problem you can already solve from a blank file, one design you can narrate, and nothing you have never seen.
- Re-read only your own notes from this week and open no new material.
- Write the logistics down: the editor or shared document you will be working in, whether execution and lookups are permitted, and the sentence you will use when you do not know something.
Deliverable: A one-page card holding the design structure, the project numbers, and the logistics.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Team size, service count and tickets closed say very little. Seniority shows in the decision you owned: what you chose not to build, which constraint you traded away, whose objection you had to resolve before anything could move. A large project where you executed someone else's plan is a small story.
How do you handle feedback from team leads or stakeholders?
How do you handle feedback from team leads or stakeholders?
Approach
- Close with what you would do differently, concretely.
- Name the disagreement and how you resolved it with evidence.
- State the situation in two sentences and spend the rest on the reasoning.
Follow-up
- How did you know your change caused the improvement?
- What did you decide not to do, and why?
Tell us about yourself and how your background prepares you for this r…
Tell us about yourself and how your background prepares you for this role.
Approach
- Give the blast radius: what could have broken, and what you measured.
- Close with what you would do differently, concretely.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Ship payouts with named, scheduled reconciliation debt
You have six working days to ship merchant payouts. The correct reconciliation join is on (external_reference, amount_minor, currency, business_date); the version that fits the window matches on amount and business_date alone, which will mismatch same-amount, same-day lines. Describe a time you shipped with debt you knew about. State exactly what you cut, the guard that made the shortcut visible rather than silent, who agreed to carry the risk, the date it was paid down, and what it cost while it stood. Be specific about the failure you were accepting.
Approach
- The probe is whether your shortcuts are bounded and instrumented or merely undocumented. Start by stating the failure you accepted in one concrete sentence: ambiguous matches will be resolved arbitrarily, so a genuine break can be masked by pairing with the wrong line.
- Make the shortcut loud rather than silent. When more than one candidate matches, do not pick one: open a break of type duplicate_match and emit a counter on that path. A shortcut that reports its own frequency converts an unknown into a number you can bring to the paydown conversation.
- Bound the exposure before you ship: query historical settlement files for lines that collide on (amount_minor, business_date) within a merchant. If that is 0.2 percent of lines, the risk is small and quantified; if it is 8 percent, the plan does not survive contact and you have learned that before shipping rather than after.
- Name the owner and the date, and say where they are written down. 'The team agreed' is the generic answer; a ticket with an owner, a date, and the counter that forces the conversation is the strong one.
- Distinguish debt you can pay from debt that compounds. A matching shortcut that leaves breaks visible is recoverable; one that auto-resolves breaks by widening a tolerance destroys the evidence and cannot be unwound later, and a strong answer says it would have refused that version even under the deadline.
- Report the actual cost: how many ambiguous matches occurred, how much analyst time they consumed, and whether the paydown date held. If it slipped, say by how long and what finally forced it.
Follow-up
- The paydown date arrives and the team has a new deadline. What do you do differently from the first conversation?
- Which shortcut would you have refused to ship at any deadline, and why that one?
- How would you have sized the exposure if no historical settlement files were available?
- 01
How do you handle feedback from team leads or stakeholders?
- 02
Tell us about yourself and how your background prepares you for this role.
- 03
You have six working days to ship merchant payouts. The correct reconciliation join is on (external_reference, amount_minor, currency, business_date); the version that fits the window matches on amount and business_date alone, which will mismatch same-amount, same-day lines. Describe a time you shipped with debt you knew about. State exactly what you cut, the guard that made the shortcut visible rather than silent, who agreed to carry the risk, the date it was paid down, and what it cost while it stood. Be specific about the failure you were accepting.
Is this an official National Payment Corporation of India interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at National Payment Corporation of India. Rounds and questions reflect what candidates have reported, not a process National Payment Corporation of India has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How long does the entire interview process typically take?
The process is designed to be efficient, often moving from the initial screening to a final decision within a few weeks. The company aims to keep the timeline quick and transparent for all candidates.
PracHub interview research ↗Should I prepare for whiteboard coding challenges?
While the interviews focus heavily on your past projects and experience, you should be prepared to discuss logic and algorithms. Interviewers focus on your problem-solving process rather than memorized syntax.
PracHub interview research ↗What differentiates successful candidates?
Successful candidates are those who can clearly articulate their technical contributions, show a deep interest in the scale and impact of the company's work, and demonstrate a collaborative, "team-first" attitude.
PracHub interview research ↗Is the interview process mostly behavioral or technical?
It is a balanced mix. Interviewers look for technical expertise to ensure you can do the job and behavioral alignment to ensure you will thrive in the company's collaborative culture.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22