Interview guides · Acra Lending
Acra Lending Software Engineer Interview Guide
Acra Lending Software Engineer interview guide: the three reported rounds, coding, integration and behavioral questions, plus a seven-day preparation plan.
The 60-second brief
Acra Lending is a mortgage lender, and candidates describe the Software Engineer role as engineering work on its mortgage loan origination systems (LOS). In their account, you build, integrate and maintain software that clients and internal teams use to move loans through the business, you work with product managers and other engineers on requirements, and the software has to meet regulatory requirements while staying usable for clients. Day to day, candidates describe code reviews, fixing production problems, and writing documentation so other engineers can follow how a system works.
This guide is for candidates preparing for the Acra Lending Software Engineer loop. It covers the three reported rounds, the reported technical, coding, behavioral and case-study questions with worked-out approaches to the behavioral ones, the stack candidates describe (Java, C# or Python, SQL and NoSQL databases, with AWS or Azure and front-end skills as extras), and the mortgage and integration background worth learning before the first call.
Candidates report three rounds over roughly 3-5 weeks: a Phone Screening, Technical Interviews that may include coding challenges and system design discussion, and a Behavioral Questions stage about your experiences and thought processes.
Focus areas
- LOS (Loan Origination System) Integration
- Integration Engineering
- Problem Solving
Overview
The work candidates describe is integration-heavy. The reported topic areas are LOS (Loan Origination System) Integration, Integration Engineering, API Integration, Problem Solving and Mortgage Domain Knowledge. In practice that means you should be comfortable explaining how two systems exchange data safely: what happens when a call times out, how you avoid applying the same update twice, how you record what changed, and how you protect personal financial data in transit and at rest.
The reported question set is general-purpose rather than domain-specific. There are language and paradigm questions (which language you know best, object-oriented versus functional programming), classic coding questions (reverse a linked list, binary search, two numbers that sum to a target, recursion, and the complexity of each), questions about performance and security, case-study questions (diagnosing a slow production system, rescuing a late project, gathering requirements for a new feature, measuring project success, balancing technical debt against features), and five behavioral questions. Prepare each as a short spoken answer with a concrete example from your own work.
The requirements candidates describe list Java, C# or Python, experience with SQL and NoSQL databases, and familiarity with Agile or Scrum. Cloud platforms (AWS, Azure), front-end basics (HTML, CSS, a JavaScript framework) and mortgage or financial-services experience are described as extras. Pick one backend language and be ready to write and explain code in it, and make sure you can discuss a relational schema and one non-relational use case without hesitation.
Because the role includes code review, production troubleshooting and documentation, your stories should show those habits: a review comment that changed a design, an incident you traced to a root cause, a document someone else used. Use the final week to turn those stories into answers with a decision, a measurement and a result.
The Acra Lending interview process
These stages are what candidates describe rather than a published process, and the reports do not say which question appears in which round, so prepare every question type for the technical and behavioral stages.
Phone Screening
Candidates report this opening call as a conversation about your background and how you fit the role. No coding or design question is tied to it in the reports, so use it to present your experience in the languages and systems the role lists and to show you understand what a loan origination system is for. Expect to be asked which language you are most comfortable with, so have a project-backed answer ready.
What to demonstrate
- How clearly you summarise your background and recent work
- Whether your stack (Java, C# or Python, plus SQL or NoSQL) lines up with the requirements candidates describe
- Whether your interest in mortgage technology is specific rather than generic
How to prepare
- Write a short spoken career summary that ends on your work closest to integrating systems or maintaining production services.
- Prepare a precise answer to "What programming languages are you most comfortable with, and why?" that names one of Java, C# or Python and a project where you used it under real constraints.
- Learn the broad stages of a mortgage loan file (application, documents, underwriting, closing) and what a loan origination system tracks, then decide which parts your experience touches.
- List two questions about the team's stack and how its systems connect to outside services.
Technical Interviews
Candidates report a series of technical interviews that may include coding challenges and system design discussion. Coding questions reported for this loop include reversing a linked list, binary search, a two-number target sum, recursion and stating complexity; the reported technical and case-study questions also cover object-oriented versus functional programming, performance, security and production diagnosis. Practise writing code by hand in one language and talking through trade-offs as you go.
What to demonstrate
- Working, readable code in your chosen language, with time and space complexity stated
- Design reasoning: components, data flow, failure handling and trade-offs
- Practical judgement on performance, security and diagnosing production problems
How to prepare
- Write the linked-list reversal (iterative, O(n) time, O(1) space), binary search and the hash-map two-sum from memory in one language, then list the edge cases for each: empty input, single element, duplicates, target not found.
- Sketch an integration between a loan-origination-style application and an outside service: synchronous call versus queue, idempotency keys so a retry does not duplicate a record, retry with backoff, and an audit trail of every status change.
- Prepare one performance story with a baseline measurement, the change and the measurement afterwards, and a security checklist covering input validation, authentication and authorization, secrets handling, encryption of sensitive data and dependency updates.
- Practise the diagnosis question as a fixed sequence: check recent deploys and dashboards, find the slow layer, inspect slow queries or traces, form one hypothesis, change one thing, verify.
Behavioral Questions
Candidates report a discussion of your experiences and thought processes. The five behavioral questions reported for this loop cover a significant project challenge, prioritizing multiple deadlines, a successful collaboration, what motivates you, and handling constructive criticism. Prepare real stories in which you made the decision and can describe the result.
What to demonstrate
- How you explain a past decision and the reasoning behind it
- Examples of working with teammates and product managers
- How you respond to feedback and competing priorities
How to prepare
- Write four stories in situation, action, result form: a hard project problem, a deadline conflict, a collaboration, and a time you received critical feedback.
- For each story, write down one number you can defend, such as incidents reduced, latency cut or days saved, and one thing you would change.
- Rehearse each story out loud using "I" for your own actions and naming teammates only for their part.
- Prepare a short, honest answer to what motivates you that points to a piece of work you actually did.
Where candidates lose points
Answering the favorite-language question with a list of technologies and the object-oriented versus functional question with two textbook definitions
Name one of Java, C# or Python and tie it to a project with a reason. For the paradigm question, give a concrete contrast: objects bundle state and behavior, while functional code favors pure functions and immutable data. Say where each helps, for example a stream or LINQ pipeline for transforming a list of loan records versus a class that models a long-lived application.
Producing a working linked-list reversal, binary search or two-sum, but skipping the edge cases and the complexity
After writing the code, run empty, single-element and duplicate inputs by hand. For binary search, check the loop bounds and the midpoint calculation. For two-sum, handle the same element being used twice. Then state time and space (O(n) and O(1) for the iterative reversal, O(log n) for binary search, O(n) with a hash map for two-sum) and the trade-off against the brute-force version.
Telling the performance, security and production-diagnosis answers as claims ("I made it faster", "I follow best practices") with no measurement or sequence
Give a baseline, the change and the measurement afterwards. For diagnosis, state your order: check recent deploys and dashboards, locate the slow layer, inspect queries or traces, form one hypothesis, change one thing, verify. For security, name specific controls: input validation, authentication and authorization, secret storage, encryption and logging.
Arriving unable to say what a loan origination system does or how systems would connect to it, even though LOS integration, API integration and mortgage knowledge are reported topic areas
Learn the basic loan lifecycle and what data moves between systems. Practise explaining integration safely: authentication, idempotent retries, handling partial failure, versioned APIs, and an audit log of changes to loan records.
Telling behavioral stories in the plural ("we decided", "we fixed it") so your own decision never appears
For each of the five reported behavioral questions, write the story with "I" for your action and one sentence on the team context. Include one number as a result and one thing you would change. Rehearse aloud until each fits in a short, structured answer.
Questions & practice
Write a function to reverse a linked list.
Medium · Coding / Algorithms
Approach
- Iterative three-pointer reversal: prev = null, curr = head; while curr is not null: next = curr.next, curr.next = prev, prev = curr, curr = next; return prev. O(n) time and O(1) extra space.
- Recursive version: if head is null or head.next is null return head; newHead = reverse(head.next); head.next.next = head; head.next = null; return newHead. Still O(n) time, but O(n) call-stack space, so a very long list can overflow the stack (Python's default recursion limit is 1000).
- Edge cases to test aloud: empty list, one node, two nodes. Forgetting to set the old head's next to null leaves a two-node cycle.
- Trace a small input before declaring it done: 1 -> 2 -> 3 should become 3 -> 2 -> 1, with prev pointing at 3 when the loop ends.
Follow-up
- Reverse only the nodes between positions m and n in one pass.
- Reverse the list in groups of k nodes, leaving a short final group as it is.
- How would you check whether a list has a cycle before reversing it (Floyd's slow and fast pointers)?
How would you implement a binary search algorithm?
Medium · Coding / Algorithms
Approach
- State the precondition: the input is sorted and supports random access. Closed-interval loop: lo = 0, hi = n - 1; while lo <= hi: mid = lo + (hi - lo) / 2; if a[mid] == target return mid; if a[mid] < target lo = mid + 1 else hi = mid - 1; return -1.
- Complexity: each step halves the range, so O(log n) comparisons and O(1) space iteratively; a recursive version uses O(log n) stack.
- Compute mid as lo + (hi - lo) / 2: in Java or C#, (lo + hi) / 2 can overflow a 32-bit int on very large arrays. Python integers do not overflow.
- Keep one invariant: either closed [lo, hi] with hi = mid - 1, or half-open [lo, hi) with hi = mid and while lo < hi. Mixing them causes infinite loops or skipped elements.
- Know the variants and library calls: lower bound (first index with a[i] >= target) for duplicates, Python's bisect_left, and Java's Arrays.binarySearch and C#'s Array.BinarySearch, which return a negative value (the bitwise complement of the insertion point) when the target is missing.
Follow-up
- Return the first and last index of a target in an array with duplicates.
- Find a target in a sorted array that has been rotated at an unknown pivot.
- Find the smallest monthly payment that pays off a loan within N months by binary searching over the payment amount. Why does that work?
Given an array of integers, find two numbers that add up to a specific target.
Medium · Coding / Algorithms
Approach
- Clarify first: return indices or values, is there exactly one answer, can the same element be used twice, can values be negative or repeated, and is the array sorted.
- Brute force: check every pair with two loops, O(n^2) time and O(1) space. Say it, then improve it.
- One-pass hash map: for each index i with value x, if target - x is already in the map return [map[target - x], i], otherwise store map[x] = i. Checking before inserting stops an element pairing with itself and still handles [3, 3] with target 6. O(n) average time, O(n) space.
- If the array is sorted, use two pointers from both ends: move left forward when the sum is too small and right back when it is too large, O(n) time and O(1) space. If it is unsorted, sorting first costs O(n log n) and loses the original indices unless you sort (value, index) pairs.
- Edge cases: no valid pair (return an empty result or raise, as agreed), negatives and zero, and in Java or C# target - x overflowing int near the limits.
Follow-up
- Return every unique pair that sums to the target, without duplicates.
- Extend it to three numbers that sum to zero. What is the best complexity you can reach?
- If the numbers arrive as a stream, how would you design add(number) and find(target)?
Explain the time and space complexity of your solutions for the previous problems.
Medium · Coding / Algorithms
Approach
- Define the terms: Big-O bounds how time or extra memory grows with input size n; state whether you mean worst, average or amortized, and whether the output counts toward space.
- Linked-list reversal: iterative O(n) time and O(1) extra space; recursive O(n) time and O(n) space for the call stack.
- Binary search: the range halves each step, so after k steps n / 2^k <= 1, which gives k = about log2 n. O(log n) time, O(1) space iteratively, O(log n) recursively.
- Two-sum: brute force O(n^2) time and O(1) space; hash map O(n) average time and O(n) space, degrading toward O(n^2) if many keys collide; sort plus two pointers O(n log n) time.
- Explain amortized cost with an example (appending to a dynamic array is O(1) amortized even though a resize copies O(n) elements), and note that constants matter: for small n a linear scan can beat building a hash map.
Follow-up
- Why is a hash-map lookup O(1) only on average, and what makes the worst case slower?
- How would you remove the O(n) stack space from a recursive solution?
- Walk through why appending to a dynamic array is amortized O(1).
Can you demonstrate how to use recursion to solve a problem?
Medium · Coding / Algorithms
Approach
- Pick a problem that is naturally recursive and state the two parts: a base case that stops, and a recursive case that works on a strictly smaller input. Good choices are tree depth, merge sort, generating subsets, or walking a nested JSON or XML document.
- Worked example: maxDepth(node) returns 0 if node is null, otherwise 1 + max(maxDepth(node.left), maxDepth(node.right)). O(n) time and O(h) stack space, where h is the tree height: O(log n) if balanced, O(n) if skewed.
- Show you can spot repeated subproblems: naive Fibonacci recursion makes an exponential number of calls; memoizing it or building it bottom-up brings it to O(n) time.
- Address stack depth: Python's default recursion limit is 1000 and Java throws StackOverflowError on deep recursion; none of Java, C# or Python guarantees tail-call elimination, so for deep inputs convert to a loop with an explicit stack.
Follow-up
- Rewrite your recursive solution iteratively with an explicit stack.
- What is the space complexity of your solution, counting the call stack?
- Generate all subsets of a set recursively. How many are there, and what is the running time?
Hold a per-tenant active cap against concurrent creates
Hard · write skew · isolation levels · constraints
A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.
Approach
- Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
- Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
- Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
- State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.
Follow-up
- A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
- The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?
Keep soft-deleted accounts from blocking re-registration
Easy · soft delete · unique constraints · engine differences
app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.
Approach
- Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
- Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
- For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
- State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.
Follow-up
- A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
- How do you honour an erasure request while resource_revision.actor_user_id still references this table?
What programming languages are you most comfortable with, and why?
Medium · Technical / Domain Questions
Approach
- Lead with one primary language and back it with evidence: what you shipped in it, how large the codebase was, and how long you worked in it. The requirements candidates describe for this role list Java, C# or Python, so if one of those is honestly your strongest, open with it.
- Give the 'why' in technical terms rather than taste: static typing and refactoring support in Java or C#, the mature JVM or .NET runtime and its libraries, or Python's fast iteration and ecosystem. Name the cost too, for example that standard CPython threads do not run CPU-bound work in parallel because of the GIL, so I reach for multiprocessing or a native library.
- Show you know one detail that matters for financial data: money is never a binary float. I use BigDecimal in Java, decimal in C# and decimal.Decimal in Python, and I set the rounding mode explicitly.
- Close with your second language and how you get productive in a new one: read idiomatic code, learn the build and test tooling first, then ship a small change.
Follow-up
- Why is a double the wrong type for a loan amount or an interest calculation, and what goes wrong if you use one?
- How does garbage collection work in your main language, and when has it caused a problem for you?
- If your background is Java, what would you need to learn first to be productive in C#?
Can you explain the difference between object-oriented and functional programming?
Medium · Technical / Domain Questions
Approach
- Define both precisely. Object-oriented code bundles state with the methods that change it and relies on encapsulation, inheritance and polymorphism through dynamic dispatch. Functional code builds programs from pure functions over immutable values, treats functions as first-class values and keeps side effects at the edges.
- Contrast how they handle state: an object mutates its fields behind methods, while a pure function returns a new value and always gives the same output for the same input. That makes pure functions easy to unit test and safe to run in parallel without locks.
- Name the extensibility trade-off (the expression problem): with classes, adding a new type is one new subclass but adding a new operation touches every class; with algebraic data types and pattern matching it is the reverse.
- Show both inside a mainstream language: Java streams and records, C# LINQ and records, Python comprehensions and functools. For example, summing a list of payments with a stream reduce versus a loop that mutates an accumulator.
- Say when you pick each: entities with a lifecycle and invariants (an application that moves through statuses) suit objects; validation and transformation pipelines over records suit a functional style. Most production code mixes the two.
Follow-up
- Is a function that writes a log line pure? Where do you put side effects like database writes in a functional design?
- When does inheritance cause trouble, and how does composition fix it?
- How would you make a class immutable in Java or C#, and what does that buy you under concurrency?
Describe a situation where you optimized an application for better performance.
Medium · Technical / Domain Questions
Approach
- Structure the story around numbers: the baseline (p95 latency, throughput, memory or job runtime), how you measured it, the bottleneck you found, the change, and the after-number measured the same way.
- Show you profiled before changing code: a sampling profiler, APM traces or EXPLAIN ANALYZE that exposed the cause, such as an N+1 query pattern, a missing index after the table grew, or a synchronous call to a slow external API.
- Name the fix and what it cost: an index speeds reads but slows writes and uses storage; batching removes round trips; a cache needs an invalidation rule and can serve stale data; moving work to a queue adds eventual consistency.
- Explain how you proved the gain came from your change and kept it: an A/B comparison or load test at equal traffic, and a regression guard such as a benchmark in CI or an alert on p95.
- Avoid the answer that sinks this question: 'I made it faster' with no number, or tuning code that was never the bottleneck.
Follow-up
- How did you rule out a traffic drop or another deploy as the real reason the numbers improved?
- What did the optimisation make worse: write speed, memory, code complexity or data freshness?
- What would you have tried next if that change had not been enough?
How do you ensure the security of the applications you develop?
Medium · Technical / Domain Questions
Approach
- Organise the answer by layer so it is complete: input handling, authentication and authorization, data protection, dependencies, and operations. Use the OWASP Top 10 as the checklist you test against.
- Injection and input: always use bind parameters or an ORM, never string-built SQL; validate input against an allowlist schema; encode output to block XSS; check file uploads by type and size.
- Authorization on the server for every request and at object level, so a user who changes an id in the URL cannot read another person's application (IDOR). Give service accounts and database roles least privilege.
- Sensitive data: mortgage applications usually hold income, account and identity details, so encrypt in transit (TLS) and at rest, mask those fields in logs, keep secrets in a secret manager rather than code or Git, and hash passwords with bcrypt or Argon2, not a fast hash like SHA-256.
- Process: dependency scanning and static analysis in CI, security items in code review, a short threat model for each new external integration, and audit logs of who read or changed a record.
Follow-up
- How would you authenticate webhooks or API calls arriving from a third-party loan system (HMAC signatures with a timestamp to stop replays, or mutual TLS)?
- Where do you keep API keys, and how do you rotate one without downtime?
- Give one example of an authentication bug and one of an authorization bug, and how each is prevented.
What tools and frameworks do you prefer for building scalable applications?
Medium · Technical / Domain Questions
Approach
- Name tools you have actually run under load, not a catalogue. The requirements candidates describe for this role list Java, C# or Python, SQL and NoSQL databases, and AWS or Azure as a plus, so map your answer onto those, for example Spring Boot, ASP.NET Core or FastAPI.
- Explain the property that makes something scale, not the brand: stateless services behind a load balancer so you can add instances, session state in a shared store, and connection pooling so instances do not exhaust the database.
- Data layer: a relational database for transactional records with the right indexes and read replicas for read-heavy paths; a NoSQL store where access is by key or documents vary in shape; a cache such as Redis with a TTL and an invalidation rule.
- Decouple slow or unreliable work with a queue (SQS, Azure Service Bus, RabbitMQ or Kafka) so a partner API outage backs up a queue instead of failing user requests; make consumers idempotent because messages can be delivered more than once.
- State the trade-off: every component adds operational load, so pick the simplest stack that meets the measured load, and add containers, infrastructure as code and metrics, logs and traces so you can see what to scale.
Follow-up
- When would you put part of this data in a NoSQL store instead of SQL, and what do you give up?
- How do you make a queue consumer safe to retry, so a redelivered message does not create a duplicate record?
- If an external API you call becomes the bottleneck, what do you change first?
How would you approach diagnosing a performance issue in a production system?
Medium · Problem-Solving / Case Studies
Approach
- Scope the symptom before touching anything: which metric moved (latency, error rate, CPU, memory), for which endpoints or users, and since when. Line that up against deploys, configuration changes, traffic and dependency incidents.
- Check resources with a method such as USE (utilization, saturation, errors) for CPU, memory and GC, thread and connection pools, and disk or network I/O. A saturated database connection pool and a CPU-bound service need different fixes.
- Narrow with traces and logs: a distributed trace shows which span dominates, whether a database query, a call to an external API, or a lock wait. For the database, use the slow query log and EXPLAIN ANALYZE, and check for lock contention or a plan that changed as data grew.
- Mitigate first if users are affected: roll back, scale out, switch the feature off with a flag, or add a timeout and circuit breaker around a slow dependency. Then reproduce and profile with JFR or async-profiler for Java, dotnet-trace for .NET, or py-spy for Python.
- Close the loop: fix the cause, confirm with the same metric, add an alert or regression test, and write a short incident review.
Follow-up
- p99 latency doubled but p50 is flat. What does that suggest, and where do you look?
- You cannot reproduce the problem in staging. What do you do next?
- Memory climbs steadily until the service restarts. How do you find the leak?
Describe the steps you would take to handle a project that is falling behind schedule.
Medium · Problem-Solving / Case Studies
Approach
- Measure the gap before reacting: remaining work against actual velocity or the burndown, which milestone slips and by how much, and why (scope growth, bad estimates, a blocked dependency, unplanned support work).
- Raise it early with options, not just bad news: cut scope to the must-haves, move the date, or change the approach. Explain why adding people late often slows a project further (Brooks's law): onboarding and coordination cost time.
- Remove blockers: escalate a stuck dependency, limit work in progress so items finish instead of all being half done, and timebox spikes on unknowns.
- Protect quality on the parts that cannot slip: keep tests on calculations, data integrity and compliance-related behaviour, and record deferred items explicitly in the backlog.
- Afterwards, run a retrospective that changes something concrete, such as how estimates are made or how much buffer is planned.
Follow-up
- The date is fixed and the stakeholder refuses to cut scope. What do you do?
- Which signals tell you a project is slipping before the deadline makes it obvious?
- The part that is slipping belongs to a teammate. How do you handle that?
If given a new feature to implement, how would you gather requirements and plan your approach?
Medium · Problem-Solving / Case Studies
Approach
- Start from the problem and the user: who uses the feature (for example a loan officer or a borrower), what task it changes, and a measurable definition of success agreed before any code is written.
- Gather functional and non-functional requirements: inputs, outputs and edge cases, expected volumes and latency, security and audit needs, and any regulatory constraint. Write acceptance criteria in Given/When/Then form and confirm them with the product manager, using a mockup or wireframe where it helps.
- Map the existing system: which services, data model changes and external APIs or integrations the feature touches. List the unknowns and resolve the riskiest with a short spike.
- Plan delivery in thin vertical slices behind a feature flag, with estimates, dependencies and risks. Include a test plan (unit tests, plus integration or contract tests for external APIs) and a rollout and rollback plan.
- Name the mistake to avoid: starting to code before agreeing what done means, then reworking it after the demo.
Follow-up
- Two stakeholders want contradictory behaviour. How do you resolve it?
- Requirements change halfway through the sprint. What do you do?
- How would you sequence a database schema change so old and new versions of the service can run side by side during rollout?
What metrics would you use to evaluate the success of a software project?
Medium · Problem-Solving / Case Studies
Approach
- Tie metrics to the goal the project set out to achieve, and record a baseline before launch so there is something to compare against.
- Outcome metrics: adoption, task completion time, error or rework rate in the workflow, and support tickets. For a lending workflow change that could be time from application to decision, or manual touches per file.
- Delivery metrics: the four DORA measures, which are deployment frequency, lead time for changes, change failure rate, and time to restore service.
- Operational and quality metrics: SLOs for availability and p95 or p99 latency, error rate, and defects found in production. Treat test coverage as a weak signal on its own.
- Warn about gaming (Goodhart's law) and vanity metrics: lines of code or story points completed say little about whether users benefited.
Follow-up
- Which metric could make a failing project look successful?
- How would you choose an SLO target for a new service?
- The project shipped on time but almost nobody uses it. Was it a success?
How do you balance technical debt with new feature development?
Medium · Problem-Solving / Case Studies
Approach
- Make debt concrete and visible: log each item in the backlog with what it costs to carry (incidents, hours lost per change, slower onboarding) and what it costs to fix, so it can be ranked against features on equal terms.
- Prioritise by interest paid: fix debt in code that changes often or causes incidents (high churn and high complexity), and leave stable code alone even if it is ugly.
- Use repeatable habits: agree a regular share of capacity with the product manager, refactor the area a feature already touches, and replace large legacy pieces gradually with a strangler-fig approach instead of a big rewrite.
- Separate deliberate debt from accidental debt: a shortcut to hit a deadline is reasonable if it is recorded with a plan to pay it back.
- Back it with a story: the debt, the number that justified fixing it, and the measured result (for example lead time or incident count before and after).
Follow-up
- The product manager says there is no time for refactoring this quarter. How do you make the case?
- When would you rewrite a component instead of refactoring it?
- Give an example of debt you chose not to pay, and explain why.
One customer endpoint stalls deliveries to every other destination
Medium · bulkhead · timeouts · saturation
The egress service delivers about 1.5k webhooks/second across 40,000 destinations, with a per-destination concurrency cap of 4 and a 10-second connect-plus-read timeout. Throughput falls to 300/second, queue depth climbs, and p99 delivery latency for unaffected destinations goes from 200 ms to minutes, while the error rate barely moves. One tenant holds 900 destination rows whose URLs share a hostname that now answers in 9.5 seconds. Explain the mechanism with the arithmetic, then give the containment in the order you would apply it.
Approach
- Look at saturation before errors. A flat error rate with collapsing throughput says nothing is failing, things are waiting, so the first signal to pull is in-flight request count or pool wait time rather than the error counter. This is the distinction that decides the whole investigation.
- Group in-flight work by resolved host, not by destination id. The cap is keyed per destination row, so 900 rows sharing one hostname buy 3,600 concurrent slots against a single host, each held for 9.5 seconds. The bulkhead was never a bulkhead for that host, and grouping by the wrong dimension is why the dashboard looked healthy.
- Do the arithmetic in both directions. Required concurrency is arrival rate times latency, so 1.5k/second at 200 ms needs about 300 in flight, which is entirely consumed by 3,600 slow slots; conversely whatever concurrency is left sustains rate equals concurrency divided by 9.5 seconds, which is the 300/second you are seeing. Matching both numbers is what promotes this from a plausible story to the mechanism.
- Explain why the circuit breaker never helped. It opens on consecutive failures, and a 9.5-second response inside a 10-second timeout is a success. Slow is not failing, so an error-rate breaker cannot see this; you need a slow-call ratio, a deadline propagated from the caller's remaining budget, or a concurrency limiter.
Follow-up
- The host recovers to 80 ms. How long does the queue take to drain, and what does the drain do to the recovered host?
- Where should the 10-second timeout number actually come from?
Suggested practice checklist
The plan follows the three reported rounds and the stack candidates describe: Java, C# or Python, SQL and NoSQL, and API integration.
Day 1 — Map the loop and your stack
- Write the three reported rounds (Phone Screening, Technical Interviews, Behavioral Questions) and next to each list which question types you must prepare.
- Pick the one language you will interview in from Java, C# or Python, and list what you can do in it without lookup: collections, string handling, recursion, a test.
- Read a short outline of the mortgage loan lifecycle and write five sentences on what a loan origination system tracks and where it connects to other systems.
Deliverable: A one-page loop map, a language choice, and a five-sentence loan origination system explanation in your own words.
Day 2 — Languages, paradigms and tooling answers
- Write your answer to "What programming languages are you most comfortable with, and why?" with a project example, then say it aloud.
- Prepare the object-oriented versus functional programming comparison with one code example of each in your chosen language and one situation where each is the better fit.
- Write a short answer on tools and frameworks you would pick for a scalable application, including how you would scale reads, writes and background work and what trade-offs you accept.
Deliverable: Three spoken answers (language choice, object-oriented versus functional, scalable-application tooling), each with a concrete example.
Day 3 — Coding fundamentals and complexity
- Write reverse a linked list iteratively, then recursively, and note the stack cost of the recursive version.
- Write binary search on a sorted array, testing duplicates, empty input and a target outside the range, then write the hash-map two-sum.
- Solve one recursion problem of your choice (for example, generating subsets or traversing a tree), then state time and space complexity for all four solutions aloud.
Deliverable: Four working solutions in your chosen language, each with its test cases and a one-line complexity statement.
Day 4 — SQL, NoSQL and API integration
- Work the practice question on holding a per-tenant active cap against concurrent creates, and write down which constraint or lock you used and why.
- Work the practice question on keeping soft-deleted accounts from blocking re-registration, and write the schema change.
- Sketch an integration between a loan-origination-style application and an external service covering synchronous versus queued calls, idempotency keys, retry with backoff and an audit table.
Deliverable: Two solved SQL practice questions and a one-page integration sketch with a failure-handling paragraph.
Day 5 — Performance, security and production diagnosis
- Write your performance story with a baseline, a change and a measurement, then your security answer as a checklist of specific controls.
- Work the practice debugging question on one customer endpoint stalling deliveries to other destinations, writing the order in which you would investigate.
- Answer "How would you approach diagnosing a performance issue in a production system?" aloud using the same sequence, ending on how you verify the fix.
Deliverable: A measured performance story, a security checklist, and a spoken diagnosis walkthrough with a verification step.
Day 6 — Case studies: schedule, requirements, metrics, debt
- Write a step list for rescuing a project that is falling behind schedule: re-estimate, cut scope, surface risks, agree a new date.
- Write how you gather requirements for a new feature: who to ask, what to confirm, how to split the work, what is out of scope.
- List the metrics you would use to judge a software project (delivery predictability, defect and incident rates, adoption) and one rule for when to pay down technical debt rather than ship features.
Deliverable: Four short written answers on schedule recovery, requirements, success metrics and technical debt, each with a real example from your work.
Day 7 — Behavioral rehearsal and phone-screen pitch
- Write four stories in situation, action, result form for the project challenge, deadline prioritization, collaboration and constructive criticism questions, using "I" for your actions.
- Write a two-sentence answer on what motivates you, backed by one example.
- Say each story aloud, then record or time the career summary you will give on the Phone Screening, and cut anything that does not support a decision or a result.
Deliverable: Five rehearsed behavioral answers plus a final career summary for the phone call.
Behavioral preparation for the final stage
Candidates report a final stage built around your experiences and thought processes. The reported questions ask about a hard project, competing deadlines, working with a colleague, what drives you, and how you take criticism. For this role, choose stories from engineering work such as an integration, an incident, a code review or a release, with a decision you made and a result you can state.
- Can you provide an example of how you resolved a conflict within a team?
Describe a time when you faced a significant challenge in a project. How did you overcome it?
Medium · Behavioral / Leadership
Approach
- Choose a project where the challenge was yours to solve: a failing integration, a missed estimate, a data migration that went wrong, or a production incident you owned. Avoid a story where the difficulty was other people and you only endured it.
- Set the situation in two sentences (system, stakes, what was going wrong), then spend most of the answer on your actions: the options you considered, why you rejected the others, and the decision you made.
- Show your method for the unknown: how you reproduced or isolated the problem, who you pulled in, and how you checked the fix before shipping it.
- Close with a result you can measure (error rate, delivery date, hours saved) and one lesson you applied afterwards, such as a test, an alert or a runbook.
Follow-up
- What would you do differently if you faced the same problem again?
- Which alternative did you reject, and why?
- How did you know your fix, rather than something else, caused the improvement?
How do you prioritize tasks when you have multiple deadlines?
Medium · Behavioral / Leadership
Approach
- Give a concrete method first: list every commitment, note who is waiting on each, separate hard deadlines (a release date, a customer or regulatory date) from soft ones, and rank by impact and by what blocks other people.
- Then ground it in one real episode: the competing items, how you ranked them, and what you moved or cut.
- Show that you renegotiated visibly: you told stakeholders what would slip and why, offered a smaller scope or a later date, and confirmed they agreed, instead of silently dropping work.
- State how you handle interruptions: a production incident outranks planned work, and you reset the plan afterwards. End with the outcome, including anything that was late and what you learned.
Follow-up
- Two stakeholders each say their request is the top priority. What do you do?
- Tell me about a deadline you missed and how you handled it.
- How do you protect time for code review and documentation when feature work is piling up?
Can you give an example of a successful collaboration with a team member?
Medium · Behavioral / Leadership
Approach
- Pick a collaboration with a specific person or pairing, such as a product manager, a QA engineer, or an engineer owning the other side of an API, and state the shared goal in one sentence.
- Say what you personally contributed and what the other person contributed. A story with no separate roles reads as generic.
- Describe how you aligned: agreeing on an interface or contract, a definition of done, how often you synced, and how you handled a disagreement with evidence such as a prototype or a measurement.
- End with the shared result and what you took from working with that person, then name a habit (written decisions, early demos, review comments) that you kept.
Follow-up
- What did the two of you disagree about, and how did you settle it?
- How do you work with someone who is not technical, such as a product manager?
- Tell me about a collaboration that did not go well and what you changed.
What motivates you to perform well in your job?
Medium · Behavioral / Leadership
Approach
- Answer with one or two specific drivers rather than a list of virtues, for example seeing a system you built carry real load, removing a recurring failure, or learning a new part of the stack.
- Back each driver with evidence from your career: a decision you made because of it, such as volunteering for an on-call rotation, writing a runbook, or staying on a migration until it was finished.
- Connect it honestly to the work this role involves (maintaining loan origination software, fixing production issues, working with product managers) without claiming to know the company's culture.
- Avoid answers that are only about pay, title or a vague "passion", and be ready to say what drains your motivation and how you handle it.
Follow-up
- What demotivates you at work, and what do you do about it?
- Describe a time your motivation dropped and how you recovered.
- If you could pick the type of project you work on, what would you choose and why?
How do you handle constructive criticism?
Medium · Behavioral / Leadership
Approach
- Choose a real piece of feedback with some sting, such as a code review that exposed a weak design, a comment on unclear communication, or a missed edge case in production. Do not disguise a strength as a weakness.
- Show your first reaction honestly, then what you did: ask clarifying questions, check whether the feedback was right, and agree on what better would look like.
- Describe the specific change in behavior (smaller pull requests, a design note before large changes, a test checklist) and give evidence it stuck, such as later review comments or fewer defects.
- Mention how it changed the way you give feedback in code review, which shows you treat the exchange as two-way.
Follow-up
- Tell me about feedback you disagreed with and what you did.
- How do you give critical feedback to a colleague in a code review?
- What is the most recent piece of feedback you acted on?