Interview guides · ADP
ADP Software Engineer Interview Guide
ADP Software Engineer interview guide: reported rounds, DSA, OOP, SQL and front-end questions, a 7-day plan and behavioral story prep.
The 60-second brief
ADP builds software for payroll, human capital management (HCM), time tracking and benefits administration. Candidate accounts name team areas such as core HCM platforms, SmartCompliance, WorkForce Software and security infrastructure, and a stack that spans Java with Spring Boot, .NET Core, Node.js and Python on the server, React and Angular on the client, and Oracle, PostgreSQL and SQL Server alongside NoSQL stores. Candidates describe software engineers working in scrum teams with sprint stories, writing and reviewing production code, automated unit and integration tests, CI/CD pipelines on tools such as Jenkins, GitLab or Bitbucket, and periodic support shifts for issues that clients report. Payroll and employee records are the domain, so rehearse the transaction and SQL questions with a pay-run example in mind.
This guide is for candidates preparing for a Software Engineer interview at ADP, whether your strength is a Java or .NET backend, Node.js or Python services, or a React or Angular front end. It covers the three reported rounds, the 24 questions candidates report across five groups (data structures and algorithms, OOP and frameworks, databases and SQL, web and front-end, behavioral), and a seven-day plan that works through them.
Candidates report three rounds over roughly 3-5 weeks: Recruiter Screening, Technical Screening and a Virtual Onsite. Reported questions are grouped by topic rather than by round, so treat the rounds as formats and prepare every topic group.
Focus areas
- Data Structures (DSA)
- Algorithms
- Problem Solving
Overview
The reported questions fall into five groups. The data structure group asks for linked-list reversal, a pair-sum search, a stack or queue built from arrays or linked lists, graph and tree traversal with the BFS versus DFS trade-off, and a string problem built on character counting or substring logic. Candidates also report the topic mix across four loops as data structures, algorithms, problem solving, Python and SQL. That mix argues for being fluent in one language at the keyboard, with complexity stated aloud for every solution you write.
The OOP and database groups are where your stack matters. Dependency injection is asked about in Spring Boot or .NET Core terms, Event versus Delegate is a C# question, and middleware is asked for .NET Core or Express.js. You do not need every framework, but you should be able to explain each concept in the one you know and map it to the others. On the database side, the Students and Marks question is an anti-join that can be written with LEFT JOIN, NOT EXISTS or NOT IN, and the answer is only complete if you can say how each treats NULLs. The index, normalisation and ACID questions reward a concrete payroll example over a recited definition.
The web group covers closures, component unit tests in Angular or React with Jest or Jasmine, HTTP methods and status codes, front-end bundle size and rendering performance, and WCAG and ARIA. Even if you target a backend team, read the posting to see how much UI work it lists. The behavioral group centres on your resume project, a technical disagreement, prioritising user stories against technical debt in a three-week sprint, and a production incident. Candidates describe the day-to-day as scrum with code review, tests and support shifts, so choose stories from work that looks like that.
The ADP interview process
Candidates describe three stages. Reports do not tie individual questions to individual rounds, so each stage below says what its format suggests and what to prepare.
Recruiter Screening
Recruiter Screening is reported as a first conversation covering your background, where you want to work and your interest in HCM, meaning human capital management software. The useful preparation is to be clear and specific about who you are as an engineer and which stack you want to work in.
What to demonstrate
- Your background and the stack you work in
- Location preferences and practical constraints
- Your stated interest in HCM and workforce software
How to prepare
- Prepare a short walk through your CV that names the language and framework you would work in (Java and Spring Boot, C# and .NET Core, Node.js, Python or a React or Angular front end) and one project that proves it.
- Write down why payroll, time tracking or benefits software interests you, tied to something you have built or used, so the answer is not generic.
- Have your location and hybrid or remote constraints ready, and ask which stack the team uses and what the later rounds contain.
- Candidates also mention an online assessment in some routes, covering aptitude, core CS concepts and coding. If the recruiter confirms one, do a timed run on one array or string problem and skim core CS concepts.
Technical Screening
The Technical Screening is reported as a remote call led by a senior engineer or team lead, with questions about your resume and short technical questions. Expect to explain your own projects in some depth and to answer short fundamentals questions clearly without a long build-up.
What to demonstrate
- Depth of understanding behind the projects on your resume
- Command of core technical concepts asked as short questions
- Clarity when explaining technical ideas aloud
How to prepare
- Pick two resume projects and rehearse the stack, your decisions, the trade-offs and one thing you would change, in the form of the walk-through-a-project question.
- Practise short spoken answers to the concept questions: stack versus queue implementation, BFS versus DFS, interface versus abstract class, clustered versus non-clustered indexes, closures, and HTTP methods and status codes.
- Keep a language-neutral version of each answer plus a version in your own language, so you can switch to whichever the interviewer names.
Virtual Onsite
The Virtual Onsite is reported as several video conversations in a row. The interviewers may include hiring managers, developers on the team and a product owner. The panel mixes technical and behavioral topics, and the reports do not say who asks what, so prepare every topic for any audience.
What to demonstrate
- Technical topics of the kinds reported: coding, SQL and framework questions
- Behavioral topics: resume project, disagreement, sprint prioritisation, production incident
- Retelling the same facts consistently across several conversations
How to prepare
- Rehearse a mixed sequence without long gaps: one coding problem (linked-list reversal or pair-sum), one SQL anti-join in two forms, one OOP and dependency-injection explanation, then a behavioral story.
- Build four story outlines (resume project, technical disagreement, sprint prioritisation against technical debt, production incident) and keep the facts identical each time you retell them.
- Prepare questions about sprint practice, testing and code review, and how support shifts are handled, and ask them to whoever is in the room, including a product owner if one joins.
Where candidates lose points
Using NOT IN for the Students and Marks anti-join without checking for NULLs in the Marks column
Write the LEFT JOIN with IS NULL, then the NOT EXISTS version, then explain that NOT IN returns no rows if the subquery yields a NULL. Test your query on sample rows that include a student with no marks and a NULL value.
Writing linked-list reversal or the pair-sum search straight away and missing empty input, a single node, duplicates or repeated use of one element
Before coding, ask whether the list can be empty, whether pairs return values or indices, and whether the same element can be used twice. After coding, trace a one-node and a two-node list by hand and state time and space, including recursion depth if you recurse.
Reciting SOLID, the four OOP principles or Event versus Delegate as definitions with no code or example from your own stack
For each principle, bring one small example: a constructor-injected service behind an interface in Spring Boot or .NET Core for dependency inversion, an abstract class versus interface choice, an EventHandler declaration in C#. Rehearse writing a middleware that checks an auth header and handles exceptions.
Answering the transaction and index questions with textbook definitions instead of a payroll-shaped scenario
Use one running example: a pay run that writes several rows and must commit or roll back as a unit. Name the isolation level, the idempotency key that stops a retry paying twice, and a case where an extra index slows writes more than it speeds reads.
Telling resume, disagreement and sprint stories in a way that never shows what you personally decided or what you gave up
For each story, write the decision you made, the alternative you rejected, and the evidence for the result. Keep the facts the same across the back-to-back conversations of the Virtual Onsite.
Questions & practice
Write a program to reverse a singly linked list and discuss its time and space complexity.
Medium · Data Structures & Algorithmic Logic
Approach
- Reverse iteratively with three references: prev starts null and curr starts at head. In each step save next = curr.next, point curr.next at prev, then move prev and curr forward one node. When curr is null, prev is the new head.
- State the cost: O(n) time and O(1) extra space. The reversal is in place, so no nodes are allocated or freed. Only the next references are rewired, which is the honest answer to the memory-management part of the question.
- Give the recursive version as an alternative: reverse the rest, then set head.next.next = head and head.next = null. It is still O(n) time but uses O(n) call-stack space, so a long list can overflow the stack. Python's default recursion limit is 1000.
- Check the edge cases out loud: an empty list (null head), a single node and two nodes. Also confirm that the old head ends with next = null, or the list becomes a cycle.
Follow-up
- Reverse only the nodes between positions m and n, leaving the rest of the list intact.
- Reverse the list in groups of k, leaving a final group shorter than k as it is.
- Use reversal to check whether a linked list is a palindrome in O(1) extra space.
Given an array of integers, identify pairs that sum up to a target value using an optimal approach.
Medium · Data Structures & Algorithmic Logic
Approach
- Clarify the contract first: return indices or values, one pair or all pairs, whether duplicates and negatives can appear, whether the input is sorted, and whether an element may pair with itself.
- Give the brute force as a baseline: check every pair, O(n^2) time and O(1) space. Then remove the inner loop.
- Optimal for unsorted input: a single pass with a hash map from value to index. For each x, look up target - x among the values already seen before inserting x. That is O(n) expected time and O(n) space, and checking before inserting stops x pairing with itself.
- If the input is sorted, or extra memory matters: sort, then move two pointers inward. Move left when the sum is too small and right when it is too large, skipping repeated values to return unique pairs. That is O(n log n) for the sort, then O(n) for the scan. Sorting loses the original indices unless you sort (value, index) pairs, and the scan is O(1) extra space only with an in-place sort, since many library sorts use O(n) or O(log n) extra space.
- When all pairs are required, keep counts instead of a set. A value equal to target / 2 needs a count of at least 2, and the output itself can be O(n^2) pairs (all zeros with target 0).
Follow-up
- Find the pair whose sum is closest to the target. Sort, run two pointers and track the smallest |sum - target|.
- Extend to three numbers summing to the target in O(n^2) time.
- How would you answer this if the array is too large for memory or arrives as a stream?
Explain how you would implement a stack or queue using basic arrays or linked lists, and handle overflow condi
Medium · Data Structures & Algorithmic Logic
Explain how you would implement a stack or queue using basic arrays or linked lists, and handle overflow conditions.
Approach
- Array stack: keep a top index. Push writes at array[top++] and pop reads array[--top], both O(1). Overflow is top == capacity. Say which policy you choose: throw, return false, or grow by doubling, which gives amortized O(1) pushes.
- Underflow matters as much as overflow. Pop or peek on an empty stack should throw or return an empty Optional, not read index -1. In Java, null out the popped slot so the array does not keep the object alive.
- Array queue: use a circular buffer with head and tail indices that wrap modulo capacity. Tell full from empty with a size counter, or by leaving one slot unused, because head == tail is ambiguous otherwise.
- Linked-list versions: a stack pushes and pops at the head. A queue keeps head and tail references, enqueues at the tail and dequeues at the head. All operations are O(1) with no fixed capacity, so overflow becomes memory exhaustion unless you enforce a maximum size.
- Trade-off: arrays give cache locality and a fixed memory footprint. Linked nodes pay a per-node pointer overhead but never need a resize copy.
Follow-up
- Implement a queue with two stacks and explain why each operation is amortized O(1).
- Add getMin() to the stack in O(1) time.
- Make the bounded queue safe for several producer and consumer threads.
How do you perform traversal on a graph or tree structure, and what are the practical differences between Brea
Medium · Data Structures & Algorithmic Logic
How do you perform traversal on a graph or tree structure, and what are the practical differences between Breadth-First Search (BFS) and Depth-First Search (DFS)?
Approach
- BFS uses a FIFO queue and visits nodes level by level, so the first time it reaches a node is by the fewest edges. That makes it the tool for shortest paths in unweighted graphs and for level-order tree output. Its memory grows with the widest level.
- DFS uses a stack, either explicit or the call stack, and goes deep before backtracking. Use it for preorder, inorder and postorder tree traversals, cycle detection, topological sort, connected components and backtracking. Its memory grows with the depth.
- Both are O(V + E) with an adjacency list, or O(V^2) with an adjacency matrix. A general graph needs a visited set because it can have cycles. In BFS, mark a node visited when you enqueue it, not when you dequeue it, or it can be queued more than once.
- Practical points: recursive DFS on a very deep graph or a degenerate tree can overflow the stack, so rewrite it with an explicit stack. On a wide, shallow structure, BFS can hold a whole level in memory.
Follow-up
- The edges now have weights. Why does BFS stop being correct, and what do you use instead?
- Detect a cycle in a directed graph with DFS, and explain why a single visited flag is not enough.
- Return the tree's nodes grouped by level, one list per level.
Solve a string manipulation problem requiring character frequency counting or custom substring logic.
Medium · Data Structures & Algorithmic Logic
Approach
- Name the problem family before coding: anagram check, first non-repeating character, longest substring without repeating characters, or minimum window containing all characters of another string.
- Counting: use an int[26] for lowercase ASCII, or a hash map for a larger or unknown alphabet. That is O(n) time and O(k) space for alphabet size k. For an anagram check, increment for one string and decrement for the other, then check that all counts are zero.
- Substring logic: a sliding window with left and right pointers. Extend right and update counts, and shrink from the left while the window breaks the rule. Each index enters and leaves the window once, so the scan is O(n).
- Edge cases: empty strings, different lengths, case sensitivity, spaces and punctuation, and characters outside ASCII. A Java char is a UTF-16 code unit, so emoji take two chars.
- Build output with StringBuilder in Java or join in Python. Repeated concatenation of immutable strings in a loop can cost O(n^2).
Follow-up
- Group a list of words into anagram sets. Compare a sorted-key signature with a count signature.
- How does your solution change for full Unicode input?
- Find all start indices where an anagram of a pattern appears in a longer string.
Explain the concept of Closure in JavaScript or TypeScript, and give a practical example of its usage.
Medium · Web & Front-End Development
Approach
- Definition: a closure is a function together with the variables of the scope it was created in. It keeps access to them after the outer function has returned.
- Practical example of private state: function makeCounter() { let count = 0; return () => ++count; }. Each counter has its own count, and no outside code can modify it. The same idea powers memoize, once and debounce, where the timer id lives in the closure.
- Classic bug: for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)) prints 3 three times, because there is one shared var binding. With let, each iteration gets a fresh binding and the output is 0 1 2.
- Costs and pitfalls: captured variables stay alive as long as the closure does, so listeners that are never removed can leak memory. In React, a stale closure in useEffect or a callback reads old state. TypeScript types do not change any of this runtime behaviour.
Follow-up
- Implement debounce and explain where the closure is.
- Why does a useEffect callback sometimes see an old state value, and how do you fix it?
- How would you find a memory leak caused by a closure?
Write a SQL query using a LEFT JOIN to identify records in a Students table that do not have corresponding
Medium · Databases & SQL Querying
Write a SQL query using a LEFT JOIN to identify records in a Students table that do not have corresponding entries in a Marks table (e.g., students who missed an exam).
Approach
- Query shape: SELECT s.student_id, s.name FROM Students s LEFT JOIN Marks m ON m.student_id = s.student_id AND m.exam_id = @examId WHERE m.student_id IS NULL;
- Put the exam filter in the ON clause. If m.exam_id = @examId moves to WHERE, the NULL rows from unmatched students are filtered out and the query returns nothing.
- Test IS NULL on a column of Marks that cannot be NULL in a real match: the join key or the primary key. A nullable column such as score would wrongly include students whose mark was recorded as NULL.
- Each unmatched student comes back once, because the anti-join keeps only rows with no match. An index on Marks(student_id, exam_id) or (exam_id, student_id) lets the engine probe matches without scanning Marks.
Follow-up
- Write the same query with NOT EXISTS, and say whether you expect a different plan.
- List every student and exam pair where the student has no mark. Cross join Students with Exams, then anti-join Marks.
- Count the students who missed each exam.
How would you rewrite a multi-table join query using an alternative approach, such as a NOT EXISTS or `NOT I
Medium · Databases & SQL Querying
How would you rewrite a multi-table join query using an alternative approach, such as a NOT EXISTS or NOT IN subquery?
Approach
- NOT EXISTS: SELECT s.* FROM Students s WHERE NOT EXISTS (SELECT 1 FROM Marks m WHERE m.student_id = s.student_id AND m.exam_id = @examId). It is correlated, and most optimizers run it as an anti semi-join.
- NOT IN has a NULL trap. If the subquery returns any NULL, x NOT IN (...) is never TRUE, so the query returns zero rows. Add WHERE m.student_id IS NOT NULL inside the subquery, or prefer NOT EXISTS.
- Set difference also works: SELECT student_id FROM Students EXCEPT SELECT student_id FROM Marks WHERE exam_id = @examId. This form returns only student_id, so join back to Students to get names. Oracle traditionally uses MINUS and has also accepted EXCEPT since 21c. Both forms remove duplicates.
- For positive joins, replace JOIN plus DISTINCT with EXISTS when you only need to know whether a match exists. The join multiplies rows, while a semi-join returns each outer row once.
- On performance, check the execution plan rather than citing a rule. NOT EXISTS and LEFT JOIN with IS NULL often produce the same anti-join. PostgreSQL cannot turn NOT IN into an anti-join because of its NULL semantics, so it can be much slower on a large subquery.
Follow-up
- A NOT IN query suddenly returns no rows after a data load. What happened?
- Which of the three forms is fastest here, and how would you show it?
- When is IN with a subquery equivalent to EXISTS?
What is the difference between clustered and non-clustered indexes, and how do they impact query execution per
Medium · Databases & SQL Querying
What is the difference between clustered and non-clustered indexes, and how do they impact query execution performance?
Approach
- A clustered index is the table itself, stored as a B-tree ordered by the clustered key, so a table can have only one. In SQL Server a primary key is clustered by default. Oracle's equivalent is an index-organized table. PostgreSQL keeps no maintained clustered order; its CLUSTER command reorders the table once.
- A non-clustered index is a separate B-tree of key columns plus a row locator. In SQL Server that locator is the clustered key, or a RID on a heap. If the query needs columns outside the index, each match costs a key lookup unless the index covers them, for example with INCLUDE.
- Impact on reads: range scans on the clustered key read contiguous pages. A selective non-clustered seek is fast, but for a predicate that matches many rows the lookups cost more than a scan, and the optimizer will choose the scan.
- Indexes can hurt. Every index is maintained on INSERT, UPDATE and DELETE. A random clustered key such as a GUID causes page splits and fragmentation. A wide clustered key is copied into every non-clustered index, so prefer a narrow, unique, ever-increasing one.
- Say what makes an index unusable: a function on the column, a leading-wildcard LIKE '%x', an implicit type conversion, or filtering on a non-leading column of a composite index.
Follow-up
- Describe a case where adding an index made the system slower.
- Design a covering index for a given query, and explain how you choose the column order.
- How do you confirm in the execution plan that the index is used?
Explain database normalisation up to Third Normal Form (3NF) and discuss situations where denormalisation is a
Medium · Databases & SQL Querying
Explain database normalisation up to Third Normal Form (3NF) and discuss situations where denormalisation is acceptable.
Approach
- 1NF: atomic column values, no repeating groups, and a key that identifies each row. 2NF: no non-key column depends on only part of a composite key. 3NF: no non-key column depends on another non-key column (a transitive dependency).
- Use one table as the example. Marks(student_id, exam_id, score, student_name) breaks 2NF, because student_name depends only on student_id. Employee(emp_id, dept_id, dept_name) breaks 3NF, because dept_name depends on dept_id. Fix each by splitting out the dependent columns.
- Explain why normalization pays off: each fact is stored once, which prevents update, insert and delete anomalies. That matters most for frequently corrected data such as employee records.
- Denormalization is acceptable for read-heavy reporting and dashboards, materialized views or precomputed aggregates, and copies that a measured slow join justifies. The cost is keeping the copies in sync, by trigger, job or application code.
- Separate denormalization from snapshots. Storing the rate that applied on a past pay record captures a different fact at a point in time; it is not a duplicate of the current rate.
Follow-up
- What does BCNF add beyond 3NF?
- How do you keep a denormalized column consistent with its source?
- Normalize a flat spreadsheet of employees, departments and managers into tables.
Explain the four fundamental principles of Object-Oriented Programming (OOP) and provide real-world examples o
Medium · Object-Oriented Programming & Core Frame
Explain the four fundamental principles of Object-Oriented Programming (OOP) and provide real-world examples of Polymorphism and Encapsulation.
Approach
- Define all four in one line each. Encapsulation hides state behind methods. Abstraction exposes what an object does, not how. Inheritance reuses and specializes a parent type. Polymorphism lets one call site work with many concrete types.
- Encapsulation example: an Employee class with a private salary field that changes only through a method that rejects negative values and records the change. Callers cannot leave the object in an invalid state.
- Polymorphism example: a PaymentMethod interface with DirectDeposit and PaperCheck implementations. The payment loop calls pay() on each one, and dynamic dispatch picks the right code. Distinguish runtime polymorphism (overriding) from compile-time polymorphism (overloading).
- Give a trade-off and not only definitions. Inheritance couples the subclass to the parent's internals, so prefer composition when the is-a relationship is weak. A subclass must remain substitutable for its parent.
Follow-up
- What is the difference between abstraction and encapsulation? Many people blur them.
- Overloading versus overriding: which one is resolved at compile time?
- Give a case where inheritance caused a problem and composition would have avoided it.
What are SOLID principles, and how do you apply Dependency Injection in a modern framework like Spring Boot or
Medium · Object-Oriented Programming & Core Frame
What are SOLID principles, and how do you apply Dependency Injection in a modern framework like Spring Boot or.NET Core?
Approach
- List SOLID with a one-line example each. Single responsibility: one reason to change. Open/closed: extend without editing. Liskov substitution: subtypes keep the parent's contract. Interface segregation: small, focused interfaces. Dependency inversion: high-level code depends on abstractions.
- Separate the terms. Dependency inversion is the principle, dependency injection supplies dependencies from outside instead of creating them with new, and the IoC container does the wiring.
- Spring Boot: annotate classes with @Service, @Repository or @Component and use constructor injection. A class with a single constructor needs no @Autowired since Spring 4.3. Use @Bean methods in a @Configuration class, and @Qualifier or @Primary when an interface has several implementations. Beans are singletons by default.
- ASP.NET Core: register services in Program.cs with AddTransient, AddScoped or AddSingleton, and receive them through constructors. Watch for captive dependencies: a scoped service injected into a singleton. Scope validation in Development throws for that.
- Explain why constructor injection is preferred: dependencies are explicit and can be final or readonly, a missing one fails at startup, and unit tests can pass mocks without a container.
Follow-up
- Explain the three .NET Core service lifetimes and a bug each one can cause.
- How do you resolve a circular dependency between two services?
- Why is field injection discouraged compared with constructor injection?
What is the difference between an interface and an abstract class, and when would you choose one over the othe
Medium · Object-Oriented Programming & Core Frame
What is the difference between an interface and an abstract class, and when would you choose one over the other?
Approach
- Abstract class: it can hold instance fields, constructors, implemented methods and protected members. A class can extend only one, in both Java and C#. Use it for closely related types that share state or a fixed algorithm skeleton (the template method pattern).
- Interface: a contract that a class can implement many of. Java 8 added default and static methods and Java 9 added private methods, but an interface has no instance fields, only constants. C# 8 added default interface members.
- Choose an interface for a capability shared by unrelated types, and for anything you inject or mock (repositories, gateways). Choose an abstract class when subclasses need shared fields or constructor logic.
- Combine them where it helps: define the interface as the public type, and add an abstract base class that implements it to share code. Callers still depend only on the interface.
Follow-up
- Two interfaces supply the same default method. What does Java make you do?
- Now that interfaces can have default methods, why would you still write an abstract class?
- How does this choice affect unit testing and dependency injection?
Explain the difference between an Event and a Delegate in C# or.NET, and write code to declare a custom event.
Medium · Object-Oriented Programming & Core Frame
Approach
- A delegate is a type-safe reference to a method with a given signature. Delegates are multicast: += combines targets, and Func<> and Action<> are the built-in generic forms. Invoking a multicast delegate with a return value gives you only the last target's result.
- An event is a member backed by a delegate with restricted access. Code outside the declaring class can only use += and -=. Only the declaring class can raise it or reassign it, so a subscriber cannot wipe the other handlers with = or raise the event itself.
- Code: declare public class PayrollProcessedEventArgs : EventArgs with the data. In the publisher write public event EventHandler<PayrollProcessedEventArgs> PayrollProcessed; and protected virtual void OnPayrollProcessed(PayrollProcessedEventArgs e) => PayrollProcessed?.Invoke(this, e);
- Explain the details: ?.Invoke reads the delegate once, so a handler that unsubscribes concurrently cannot cause a null reference. The publisher holds references to its subscribers, so a forgotten -= keeps them alive (a memory leak). An exception in one handler stops the handlers after it.
Follow-up
- When would you write custom add and remove accessors for an event?
- How do you track down a memory leak caused by event subscriptions?
- What goes wrong with async void event handlers?
Describe how custom middleware works in.NET Core or Express.js and write a basic implementation.
Medium · Object-Oriented Programming & Core Frame
Approach
- Describe the model. A request passes through an ordered chain of components. Each one can act before passing the request on, act after the rest of the pipeline returns, or short-circuit with its own response. Registration order is execution order.
- ASP.NET Core: write a class whose constructor takes a RequestDelegate next, with public async Task InvokeAsync(HttpContext context) that runs logic, then await next(context). Register it with app.UseMiddleware<T>() or inline with app.Use. Inject scoped services as InvokeAsync parameters, because the middleware instance is created once.
- Express.js: a middleware is (req, res, next) => {...} that either calls next() or ends the response. Error middleware has four parameters (err, req, res, next) and is registered last. In Express 4, async errors must be passed to next(err); Express 5 forwards rejected promises itself.
- Write a concrete example. An auth-header check returns 401 when the header is missing or invalid. A global exception handler is registered first so it wraps everything and returns a consistent 500 JSON body. A timing or correlation-id middleware writes to the log.
- Edge cases: do not change headers after the response has started. ASP.NET Core throws an InvalidOperationException when headers are modified at that point, so check context.Response.HasStarted. Express raises ERR_HTTP_HEADERS_SENT, so check res.headersSent. Do not call next() after already sending a response.
Follow-up
- In ASP.NET Core, when would you use an MVC action filter instead of middleware?
- Why must authentication middleware come before authorization, and what breaks if they are swapped?
- How would you unit test this middleware?
How do you manage database transactions and ensure ACID compliance when handling critical financial or payroll
Medium · Databases & SQL Querying
How do you manage database transactions and ensure ACID compliance when handling critical financial or payroll data?
Approach
- Define ACID briefly. Atomicity: all of the change commits or none of it does. Consistency: constraints hold after commit. Isolation: concurrent transactions do not see each other's partial work. Durability: committed data survives a crash, through the write-ahead or transaction log.
- Wrap every row of one business change, such as a pay record and its ledger lines, in a single transaction. In Spring, @Transactional rolls back on unchecked exceptions by default but not on checked ones unless you configure rollbackFor. In .NET, use a DbContext transaction or TransactionScope.
- Isolation: Read Committed is the default in SQL Server, PostgreSQL and Oracle. Name the anomalies (dirty read, non-repeatable read, phantom, lost update). Prevent lost updates with SELECT ... FOR UPDATE, UPDLOCK in SQL Server, or optimistic concurrency with a version or rowversion column.
- Let the database enforce correctness. Use DECIMAL or NUMERIC for money, never floating point. Add CHECK and foreign-key constraints, and a unique constraint on the business key (such as employee plus pay period) so a retried request cannot pay twice.
- Keep transactions short, with no remote calls inside them. Retry deadlock victims, and take locks in a consistent order. When a change spans services, use the outbox pattern or a saga instead of a distributed transaction.
Follow-up
- Two sessions update the same balance at the same moment. Walk through what happens under Read Committed.
- How do you handle a deadlock that your application hits in production?
- The payroll write and a notification live in different services. How do you keep them consistent?
How do you write component unit test cases in Angular or React using frameworks like Jest or Jasmine?
Medium · Web & Front-End Development
Approach
- Use the Arrange, Act, Assert structure, and test what the user sees and does rather than internal state or private methods. Cover the loading, success, empty and error states.
- React with Jest and React Testing Library: render the component, query by role or label (getByRole('button', { name: /save/i })), interact with user-event, and assert on the DOM. Use await findBy... for asynchronous content.
- React data mocks: mock the API module with jest.mock or intercept the network with MSW. Assert that the component handles both a resolved and a rejected request.
- Angular with Jasmine and Karma or Jest: set up TestBed.configureTestingModule (standalone components go in imports). Provide the service as a mock with { provide: EmployeeService, useValue: jasmine.createSpyObj('EmployeeService', ['getAll']) }, then call fixture.detectChanges().
- For HTTP in Angular, use provideHttpClientTesting (HttpClientTestingModule in older versions) with HttpTestingController to expect and flush a response. Use fakeAsync and tick for timers. Use snapshot tests sparingly, because they break on harmless markup changes.
Follow-up
- How do you test a component that fetches data when it loads?
- Would you mock child components or render them for real, and why?
- Where do unit tests stop and integration or end-to-end tests begin?
Explain HTTP methods, REST API conventions, and common HTTP status codes used in client-server communication.
Medium · Web & Front-End Development
Approach
- Methods: GET is safe and idempotent. POST creates and is not idempotent. PUT replaces a resource and is idempotent. PATCH applies a partial update and is not guaranteed idempotent. DELETE is idempotent.
- REST conventions: resources are plural nouns (/employees/{id}/paystubs), and the server keeps no session state per request. Filtering, sorting and pagination go in query parameters, the API has a versioning scheme, and JSON error bodies are consistent.
- Status codes: 200 OK, 201 Created with a Location header, and 204 No Content. Then 400 for a malformed request, 401 for unauthenticated and 403 for authenticated but not allowed. Then 404, 409 Conflict, 422 for validation errors and 429 for rate limits. On the server side: 500, plus 502, 503 and 504 from gateways or overload.
- Make POST safe to retry by accepting an Idempotency-Key header and storing the result per key, so a client that times out can retry without creating a duplicate.
- Common mistakes: returning 200 with an error in the body, mixing up 401 and 403, and using GET for actions that change state.
Follow-up
- When do you choose PUT over PATCH?
- Compare offset pagination with cursor pagination on a large, frequently changing table.
- How would you version this API without breaking existing clients?
How do you optimize web application performance on the front end, particularly regarding bundle size and rende
Medium · Web & Front-End Development
How do you optimize web application performance on the front end, particularly regarding bundle size and rendering efficiency?
Approach
- Measure before changing anything. Use Lighthouse and Core Web Vitals (LCP, INP, CLS), the DevTools Performance panel, React Profiler or Angular DevTools, and a bundle analyzer such as webpack-bundle-analyzer or source-map-explorer.
- Bundle size: split code by route with dynamic import(), using React.lazy with Suspense or Angular lazy routes (loadChildren and loadComponent). Rely on tree shaking of ES modules, import only the functions you use, replace heavy libraries, and serve compressed, content-hashed files with long cache lifetimes.
- Rendering in React: prevent unnecessary re-renders with React.memo, useMemo and useCallback where profiling shows a cost, and use stable keys. Keep state close to where it is used so updates do not re-render the whole tree.
- Rendering in Angular: use OnPush change detection and trackBy (or track in @for). Virtualize long lists (react-window, CDK virtual scroll), and debounce input-driven work.
- Network and assets: use responsive, lazily loaded images in modern formats, preload critical fonts and scripts, and avoid layout shift by reserving space for images and ads.
Follow-up
- A table page feels slow when typing in its filter box. How do you find the cause?
- What does server-side rendering improve, and what does it cost?
- Which metric would you report to show your change worked?
What are accessibility standards such as WCAG and ARIA, and how do you integrate them into UI components?
Medium · Web & Front-End Development
Approach
- WCAG is the W3C guideline set, organised around four principles: perceivable, operable, understandable and robust. It has conformance levels A, AA and AAA, and AA is the usual target. WAI-ARIA adds roles, states and properties that expose meaning for custom widgets to assistive technology.
- First rule of ARIA: prefer native HTML. A <button> already has a role, focus behaviour and Enter and Space handling, while a clickable <div> needs all of that added by hand.
- Component checklist: a label tied to every input (label for/id, aria-label or aria-labelledby) and alt text for images. Full keyboard operation with a visible focus indicator and no keyboard traps. Focus moved into a modal and returned on close, aria-live for asynchronous updates and form errors, and contrast of at least 4.5:1 for normal text at AA (3:1 for large text).
- Testing: run automated checks with axe-core or jest-axe in unit tests and Lighthouse in CI. Do a keyboard-only pass and a screen-reader pass (NVDA, VoiceOver), because automated tools catch only part of the issues.
Follow-up
- Build an accessible modal dialog: what do focus, keyboard and ARIA attributes need to do?
- When do you use aria-label, aria-labelledby or aria-describedby?
- How would you stop accessibility regressions from reaching production?
Tell me about a time a production issue occurred in your code. How did you debug, resolve, and prevent it from
Medium · Behavioral & Past Project Experience
Tell me about a time a production issue occurred in your code. How did you debug, resolve, and prevent it from recurring?
Approach
- Choose an incident where your own code was at fault and you drove the fix. Open with the symptom and its impact in terms you can verify: which users, which feature, and for how long.
- Walk through the debugging in order. Say how it was detected, then how you scoped it (which requests, since when) and checked what changed at that time (deploy, config, data). Then reproduce it from logs or traces, and confirm the hypothesis before changing code.
- Show that you mitigated before searching for the root cause: rollback, feature flag or data correction. Then separate the trigger from the cause, for example a release that first exposed a missing null check, a time zone boundary or a race condition.
- Close with prevention you actually shipped: a regression test that reproduces the bug, a monitor or alert that would catch it sooner, and a fix to the review or test gap. Mention a blameless write-up if there was one.
- The answer falls apart if you blame a teammate or another team, say only 'I fixed it' without the steps, or end without any prevention.
Follow-up
- How did you confirm that your fix resolved it and did not just hide the symptom?
- Why did your existing tests miss this bug?
- What alert would have caught it before users noticed?
Suggested practice checklist
The plan follows the reported loop: one day to map the stages and choose your stack, five days on the reported question groups in the order they are listed, and a final day of behavioral outlines plus a mixed mock. Each day produces something you can check, such as running code or a written story.
Day 1 — Map the loop and choose your stack
- Write the three reported rounds (Recruiter Screening, Technical Screening, Virtual Onsite) and note under each which question groups you will rehearse.
- Pick one language for live coding and check the target posting for its stack, for example Spring Boot or .NET Core, React or Angular.
- List three resume projects with your role, the stack and a measurable outcome for each.
- If the recruiter confirms an online assessment, do one timed run on an array or string problem and review core CS concepts.
Deliverable: A one-page loop map, the chosen coding language, and a list of three resume projects with role, stack and outcome.
Day 2 — Linked lists, pair sums and string counting
- Implement iterative linked-list reversal with previous, current and next pointers, then a recursive version; state time and space for both and test empty, one-node and two-node lists.
- Write the pair-sum search two ways: a one-pass hash map (value to index) in O(n) time, and a sort plus two pointers that is O(1) extra space only with an in-place sort. Sort (value, index) pairs if you must return original indices, and decide how duplicates are handled.
- Solve one frequency-count string problem such as anagram check or first unique character, using a fixed-size array and then a hash map.
Deliverable: Three working solutions with edge-case tests and a one-line complexity statement for each.
Day 3 — Stacks, queues and graph traversal
- Build an array-backed stack and a circular-buffer queue with an overflow policy (reject or grow by doubling), then linked-list versions of both.
- Write BFS with a queue and DFS both recursively and with an explicit stack, on a tree and on a graph with a visited set.
- Write bullet points comparing BFS and DFS: shortest path in an unweighted graph, memory use for wide versus deep structures, and cycle handling.
Deliverable: Four tested implementations plus a written BFS versus DFS comparison you can say aloud.
Day 4 — OOP, SOLID, dependency injection and middleware
- Write the four OOP principles with one example each, using polymorphism and encapsulation examples from your own language.
- Refactor a small class to fix a single-responsibility violation, then wire it through constructor injection behind an interface in Spring Boot or .NET Core and test it with a fake.
- Write a one-page table of interface versus abstract class, then declare a custom event with EventHandler in C# if .NET is your stack.
- Write a middleware (.NET Core pipeline or Express next function) that validates an auth header and handles exceptions globally.
Deliverable: A one-page notes sheet and a small code sample containing an injected service, a custom event or interface example, and a middleware.
Day 5 — SQL, indexes, normalisation and transactions
- Create Students and Marks tables with a student who has no marks, then write the anti-join with LEFT JOIN and IS NULL, with NOT EXISTS, and with NOT IN; show what NOT IN does when the subquery returns a NULL.
- Read the execution plan for each version and sketch how a clustered index differs from a non-clustered one, including a case where an extra index hurts write-heavy tables.
- Normalise a payroll table to Third Normal Form and name one place where you would denormalise for reporting.
- Write a transaction script for a pay run covering commit, rollback, isolation level and an idempotency key.
Deliverable: A SQL file with the three anti-join queries and observed results, a 3NF schema, and a transaction script with notes.
Day 6 — Closures, component tests, HTTP and accessibility
- Write a counter factory, a memoise function and a once wrapper to explain closures, and show the var versus let loop-capture bug.
- Write a component test in React with Jest or in Angular with Jasmine, mocking the backend service dependency.
- Make a table of HTTP methods (safe and idempotent or not) and the status codes 200, 201, 204, 400, 401, 403, 404, 409 and 500.
- List front-end performance levers (code splitting, lazy routes, tree shaking, memoisation, list virtualisation) and WCAG and ARIA basics: semantic HTML first, labels, focus order, keyboard access.
Deliverable: A tested component, a one-page HTTP reference and a front-end performance and accessibility checklist.
Day 7 — Behavioral outlines and a mixed mock
- Write outlines for the resume project, technical disagreement, sprint prioritisation and production incident stories, each with the decision, the alternative rejected and the evidence.
- Run a mixed back-to-back mock: one coding problem, one SQL anti-join, one OOP or dependency-injection question, then two behavioral prompts, answered aloud.
- Write the questions you would ask a hiring manager and a product owner about sprints, testing, code review and support shifts.
Deliverable: Four written story outlines, a recorded or noted mock with gaps marked, and a list of questions to ask.
Project, disagreement and sprint stories
Candidates report behavioral prompts anchored in your own work: a project on your resume, a technical disagreement, prioritising stories against technical debt, and a production issue you fixed. Rehearse each as a story with a clear personal decision, the alternative you rejected and evidence of the result, because the same facts may be retold to several people in a row.
- Tell me about a time a production issue occurred in your code. How did you debug, resolve, and prevent it from recurring?
Walk me through a challenging project listed on your resume, detailing your specific role, technical choices,
Medium · Behavioral & Past Project Experience
Walk me through a challenging project listed on your resume, detailing your specific role, technical choices, and outcomes.
Approach
- Choose a resume project you can defend line by line, where you owned a real decision such as a schema, an API contract, a framework choice or a migration. Anything on your resume can be asked about in detail, so skip work you cannot explain below the headline.
- Give the context in two sentences (the system, who used it, your role, team size) and spend most of the answer on technical choices: the options you weighed, the one you picked, and the trade-off you accepted, in the form "I chose X over Y because...".
- Close with an outcome backed by evidence you gathered yourself, such as query latency before and after, error rate, release frequency or test coverage. If you have no number, say what you observed and how you checked it.
- Say what you personally did in first-person singular and name teammates for their parts. A story that never separates your contribution from the team's is the common way this answer fails.
- Finish with one thing you would change today, which shows you reviewed your own design.
Follow-up
- Why did you choose that approach over the alternative, and what would have made you pick the other one?
- How did you verify that your change caused the improvement you describe?
- What would you do differently if you ran the project again?
Describe a situation where you had a technical disagreement with a team member or project lead. How did you re
Medium · Behavioral & Past Project Experience
Describe a situation where you had a technical disagreement with a team member or project lead. How did you resolve it?
Approach
- Choose a disagreement about something that can be checked, such as synchronous versus asynchronous calls, adding an index versus denormalising, a library choice, or where to draw an interface boundary. Avoid a story that is really about personality.
- State both positions fairly in a sentence each, including the strongest argument for the other person's view. This shows you understood it rather than just outlasted it.
- Describe how evidence settled it: a small spike, a benchmark, a query plan, the framework documentation, or a written comparison taken to the tech lead. Evidence beats seniority and volume.
- Report the outcome honestly, including if you were wrong or the result was a compromise, and say what you changed afterward, for example agreeing decision criteria before debating options.
- The mistake that sinks this answer is a story where the other person was simply wrong and you won. Show the working relationship afterward.
Follow-up
- What would you have done if the lead had still disagreed after seeing your evidence?
- The decision turned out to be wrong in production. How do you handle that?
- How do you raise a technical objection during code review without stalling the pull request?
Give an example of how you prioritized user stories or technical debt during a tight three-week sprint cycle.
Medium · Behavioral & Past Project Experience
Approach
- Set the constraints in the first sentences: the sprint length (three weeks in this question), the stories already committed, the debt item at stake (flaky tests, an outdated dependency, a missing index, a brittle deployment step) and who had a stake, such as the product owner and teammates.
- Show a ranking method rather than a feeling: weigh user impact and deadline against the risk and ongoing cost of the debt, and make the debt visible with evidence such as failed builds, support tickets or time lost per release.
- Describe the negotiation with the product owner: slice a story smaller, attach the debt fix to a story that touches the same code, or reserve a fixed share of capacity. Show you brought options, not just a complaint.
- Name what you deferred and how you recorded it, for example a backlog item with a trigger condition, and report what happened at the sprint review.
- The mistake that sinks this answer is claiming everything was delivered. A prioritisation story needs a visible cut and the reasoning behind it.
Follow-up
- An urgent production support request arrives mid-sprint. What do you drop, and who do you tell?
- How would you convince a product owner to spend sprint capacity on debt that users cannot see?
- Looking back, was the item you deferred the right one to cut?