Interview guides · Cenlar FSB
Cenlar FSB Software Engineer Interview Guide
Cenlar FSB Software Engineer interview guide: both reported rounds, the reported questions with answer plans, and a 7-day prep plan.
The 60-second brief
Cenlar FSB is a financial services company. Candidates describe a Software Engineer role that touches a range of products, from loan servicing platforms to applications that clients use directly, where the software has to fit business goals, user needs and regulatory requirements. The reported responsibilities are everyday engineering work: designing, coding, testing and maintaining software, reviewing teammates' code, working with product managers and quality assurance, and tracking down defects. Nothing reported names a specific team, framework or architecture, so treat the stack as the list of skills candidates describe rather than a known system.
This guide is for engineers with roughly three to five years of software development experience who are preparing for the Cenlar FSB Software Engineer loop. It covers both reported rounds, the twenty reported questions (language fundamentals, coding, debugging and design reasoning, and behavioral stories), the skills the role lists (Java, C# or Python, SQL and NoSQL, web basics, Git, algorithms and data structures, cloud as a plus) and a plan for turning them into spoken answers.
Candidates report two rounds over about 2-4 weeks: a behavioral interview with a manager, then a technical interview with a panel of developers. The reported questions mix language fundamentals, coding, production troubleshooting and teamwork stories.
Focus areas
- Cloud Infrastructure
- Engineering Operations (Engineering Ops)
- Software Engineering (General)
Overview
The reported loop is short, so each conversation carries weight and neither can be skipped in preparation. The first is a conversation with a manager about your background, your reasons for wanting the role and how you fit it. The second is a panel of developers looking at your coding skills and technical knowledge. Prepare two different kinds of material: a small set of true stories you can tell with specifics, and a set of technical explanations you can give out loud while writing code.
The reported questions split into four groups. Language and tooling questions ask about synchronous versus asynchronous programming, memory management in your preferred language, version control and API integration. Coding questions ask for a string reversal with complexity, a sorting or searching challenge, a data structure of your choice, unit testing and test-driven development, and ways to speed code up. Case-style questions ask you to optimize performance for a scenario, debug a complex production issue, weigh architectural trade-offs, build a feature into an existing application and keep code maintainable. Behavioral questions cover pressure, conflict, prioritizing deadlines, initiative and values.
Because candidates describe work on loan servicing platforms and client-facing applications under regulatory requirements, it helps to frame your examples around correctness, careful change, testing and traceability rather than raw speed. The requirements candidates report also list SQL and NoSQL databases, HTML, CSS and JavaScript, Git, and a plus for AWS or Azure, DevOps practices and automated testing frameworks. You do not need to master all of them, but you should be able to say honestly where you have used each one and where you have not.
The most useful habit for this loop is saying your reasoning aloud. Several reported questions are open-ended (explain, describe, discuss), and a strong answer names a mechanism, gives a trade-off and ends with a concrete example from your own work. Practise each answer until you can give a short version and a longer version, and keep one real incident ready that works for both the technical-problem question and a behavioral prompt.
The Cenlar FSB interview process
Candidates report two stages: a manager-led behavioral interview first, then a technical interview with a panel of developers. The overall process is reported at about 2-4 weeks.
Behavioral Interview
Candidates report that the opening round is a conversation with a manager about your background, what draws you to the role and how well it suits you. It is a behavioral stage, so it is where behavioral-type questions (pressure, conflict, priorities, initiative, values) are practised. Approach it as a structured walk through your career: a short summary of what you have built, a specific reason for wanting a software role in financial services, and two or three stories where you made a decision and can state the result.
What to demonstrate
- Your background and how your past work connects to a Software Engineer role
- Your motivations for this role and company
- Fit for the role, shown through concrete stories about teamwork, priorities and pressure
How to prepare
- Write a short summary of your career covering the languages, databases and tools you have used, ending on why this role next.
- Prepare a story bank of three or four real situations (pressure, conflict, competing deadlines, initiative) and write each in situation, action, result form with your own decision named.
- Connect your motivation to the reported work: loan servicing platforms, client-facing applications and regulatory requirements. Say what interests you in building software under those constraints.
- Prepare two or three questions for the manager about the team's engineering practices, code review and release process.
Technical Interview
Candidates report that the second round is a panel of developers assessing your coding skills and technical knowledge. A stage with this format is where coding questions are practised, along with language fundamentals and reasoning about production issues. The reported question types include reversing a string with complexity analysis, sorting or searching, implementing a data structure, unit testing, version control, API integration, performance and debugging. Approach it by thinking aloud, stating complexity, testing your own code on edge cases, and giving examples from real projects.
What to demonstrate
- Working code and correct complexity reasoning on data structure and algorithm problems
- Command of language fundamentals such as asynchronous programming, memory management and version control
- How you structure a response to debugging, performance and design-trade-off scenarios
How to prepare
- Pick one language from Java, C# or Python (the ones the role lists) and write each coding answer in it by hand, including a linked list, string reversal, binary search and a comparison of sorting algorithms.
- Rehearse a production-debugging answer as a fixed sequence: stabilise, find what changed, form a hypothesis, test it, fix, then prevent recurrence.
- Write a one-page explanation of asynchronous versus synchronous programming and of memory management in your chosen language, with one example each from your own work.
- Prepare to describe your Git workflow (branching, pull requests, review, resolving conflicts) and your approach to unit tests, including what you would test first on a new function.
Where candidates lose points
Answering the memory-management question with 'the garbage collector handles it'
Name the mechanism for your language (generational tracing GC in Java and C#, reference counting plus a cycle collector in Python), describe one way a managed program still leaks (an unbounded cache, a forgotten listener, an unclosed resource) and say how you would find it with a heap dump or profiler.
Treating the string-reversal or sorting question as trivial and writing it without analysis
State time and space complexity aloud, note that strings are immutable in Java, C# and Python so a reversal builds a new O(n) string, show an in-place two-pointer version on a character array, and test empty, single-character and non-ASCII input. For sorting, compare algorithms by worst case, stability, memory and how they behave on nearly sorted data.
Telling every behavioral story as 'we' with no personal decision in it
For the pressure, conflict, priority and initiative questions, write each story in situation, action, result form and name the decision you made, what you gave up, and what you changed afterwards.
Describing production debugging as 'I would look at the logs' with no order of operations
Give the sequence: stop the damage (roll back, flag off or scale), establish what changed and when, check that the monitoring is trustworthy, form one testable hypothesis at a time, fix, then add the test or alert that would have caught it.
Giving a generic motivation in the manager round
Connect your reasons to the reported work: loan servicing platforms, client-facing applications and regulatory requirements. Be specific about why building software under those constraints interests you and which parts of your own experience fit.
Questions & practice
Explain the differences between synchronous and asynchronous programming.
Medium · Technical / Domain Questions
Approach
- Define it precisely. A synchronous call blocks the caller until the result is ready. An asynchronous call starts the operation and gives control back at once, and the result arrives later through a callback, a promise/future or an await continuation.
- Separate concurrency from parallelism. A single-threaded event loop (Node.js, Python asyncio) can keep thousands of I/O waits in flight without running anything in parallel. CPU-bound work inside an async handler still blocks the loop, so it belongs in a thread or process pool (run_in_executor, worker threads).
- Use the languages listed for the role. C# has async/await over Task, and calling .Result or .Wait() can deadlock where there is a synchronization context. Java has CompletableFuture. Python has asyncio coroutines. JavaScript has promises with async/await.
- Give a concrete gain. Three independent API calls awaited one after another take the sum of their latencies. Task.WhenAll, Promise.all or asyncio.gather brings the total close to the slowest single call.
- Name the costs: harder stack traces, errors that must be propagated or they get lost, cancellation and timeouts, and back-pressure. For a short sequential script or CPU-bound job, synchronous code is simpler and fine.
Follow-up
- What happens if you call a blocking database driver inside an async request handler, and how would you fix it?
- How do you cap concurrency so a fan-out of async calls does not overload a downstream service?
- How do you propagate a timeout or cancellation through a chain of awaited calls?
Write a function to reverse a string. Discuss the time and space complexity.
Medium · Coding / Algorithms
Approach
- Two pointers on a mutable character array: swap s[i] and s[j], then move i forward and j back until they meet. That is O(n) time and O(1) extra space.
- Strings are immutable in Java, C# and Python, so you must allocate a copy, which makes space O(n). Idioms: new StringBuilder(s).reverse().toString() in Java, ToCharArray plus Array.Reverse plus new string in C#, s[::-1] in Python.
- Avoid building the result with += in a loop. Each concatenation can copy the whole string, giving O(n^2) time in Java and C#. A recursive version uses O(n) stack depth, risks stack overflow on long input, and becomes O(n^2) if it slices substrings.
- Edge cases: null versus empty input, a single character, and Unicode. Reversing UTF-16 code units splits surrogate pairs (emoji) and detaches combining marks. Java's StringBuilder.reverse keeps surrogate pairs together, but full grapheme clusters need StringInfo (C#) or BreakIterator (Java).
- Test on empty, one character, even and odd lengths, and a string with an emoji.
Follow-up
- Reverse the order of words in a sentence in place (reverse the whole string, then each word).
- How would you handle emoji and accented characters correctly?
- Write it recursively. What are the time and space complexity?
Solve a coding challenge involving sorting or searching algorithms.
Medium · Coding / Algorithms
Approach
- Ask about input size, whether it is already sorted, duplicates, the value range and memory limits. These decide the algorithm.
- Binary search on sorted data is O(log n). Use mid = lo + (hi - lo) / 2 to avoid integer overflow in Java and C#, and know the lower-bound variant for finding the first or last occurrence of a duplicated value.
- Know the sorting trade-offs. Merge sort is O(n log n) worst case, stable, with O(n) extra space. Quicksort averages O(n log n) and sorts in place but is O(n^2) in the worst case and unstable. Heap sort is O(n log n) with O(1) extra space and unstable. Insertion sort wins on small or nearly sorted input. Counting sort is O(n + k) for a small integer range.
- Know your library. Java's Arrays.sort uses dual-pivot quicksort for primitives and stable TimSort for objects. C# Array.Sort is an unstable introsort. Python's sort is stable (Timsort). Sorting first often enables two pointers or binary search.
- Test the edges: an empty array, one element, all duplicates, a target that is absent, and a target at either end.
Follow-up
- Find the first and last position of a target in a sorted array with duplicates.
- Search a rotated sorted array in O(log n).
- How do you sort data that does not fit in memory, or find the top k items in O(n log k)?
Explain how you would implement a data structure of your choice.
Medium · Coding / Algorithms
Approach
- Pick a structure you can code completely. State its operations and target complexities before writing anything, for example a linked list, a dynamic array or an LRU cache.
- Linked list: a node class with value and next (and prev if doubly linked), plus head and tail pointers. Insert at the head is O(1), append with a tail pointer is O(1), search is O(n). Sentinel nodes remove the special cases for an empty list or removing the head.
- Dynamic array: when full, double the capacity and copy the elements. Appends are then amortized O(1), even though a single resize is O(n).
- LRU cache: a hash map from key to node plus a doubly linked list ordered by recency. get and put are both O(1). Move a node to the front on access and evict from the tail when over capacity.
- Walk through edge cases aloud (empty structure, one element, removing the tail, capacity zero) and trace a short sequence of operations to show it works.
Follow-up
- Reverse a singly linked list iteratively in O(n) time and O(1) space.
- Why does the LRU cache need a doubly linked list rather than a singly linked one?
- How would you make your structure thread-safe, and what does the locking cost?
Describe how you approach unit testing and test-driven development.
Medium · Coding / Algorithms
Approach
- Describe the TDD loop: write a failing test (red), write the minimum code to pass it (green), then refactor with the test as a safety net. Say when you use it (well-understood logic, bug fixes) and when you do not (exploratory spikes).
- A good unit test checks one behaviour, is fast and deterministic, follows Arrange-Act-Assert and has a name that states the expected behaviour.
- Isolate dependencies such as the database, HTTP calls and the clock by injecting them and replacing them with stubs or mocks. Name frameworks from the stack: JUnit 5 with Mockito, xUnit or NUnit with Moq, pytest with unittest.mock.
- Pick boundary cases from the domain. For a payment or interest calculation, test zero, negative and rounding edges, and use decimal types (BigDecimal, decimal) rather than floating point for money.
- Name the anti-patterns: over-mocking that ties tests to implementation details, tests that depend on execution order or the real time, and chasing a coverage percentage.
Follow-up
- How do you unit test code that depends on the current date or time?
- What is the difference between a mock and a stub, and when do you use each?
- A test fails intermittently in CI. How do you track it down?
What are your strategies for optimizing code performance?
Medium · Coding / Algorithms
Approach
- Measure before changing anything. Use a profiler (Java Flight Recorder or VisualVM, dotnet-trace, cProfile or py-spy, browser devtools) and a benchmark harness with warm-up (JMH, BenchmarkDotNet, timeit), and set a target.
- Fix the algorithm first. Replacing a nested-loop lookup, O(n^2), with a hash set or map, O(n), usually beats any micro-optimization.
- Fix I/O next. Remove N+1 queries with joins or batching, add the right indexes, cut chatty network calls, paginate, and stream large datasets instead of loading them all into memory.
- Then reduce allocation and repeated work: StringBuilder in loops, reusing buffers, avoiding boxing in hot paths, memoization or caching, and running independent I/O concurrently.
- Re-measure under the same conditions and stop at the target. By Amdahl's law, speeding up a part that takes 5% of the run time gains at most about 5%, so only optimize what the profile says matters.
Follow-up
- The profile shows no single hotspot. What do you do?
- How would you find and confirm a memory leak?
- When is an optimization not worth the readability cost?
Explain why the owner filter ignores the listing index
Medium · composite index · query plans · sort elimination
The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.
Approach
- Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
- For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
- Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
- Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.
Follow-up
- 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
- A dashboard runs this for 40 owners in one page load. What changes about the design?
Stop tag and share joins from fanning out a page
Medium · join fan-out · semi-joins · many-to-many
resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.
Approach
- Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
- Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
- Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
- Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.
Follow-up
- The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
- A resource can be shared with the same user twice under different permissions. Does your count change, and should it?
Describe a challenging technical problem you solved in a previous role.
Medium · Technical / Domain Questions
Approach
- Pick a problem with a measurable symptom and real constraints, such as a slow batch job, data corruption, a memory leak or a hard integration. Avoid one whose difficulty was only the amount of work.
- Set out the technical context in two or three sentences: the system, the scale, and why the obvious fix did not work.
- Walk through the hypotheses you ruled out and the evidence that ruled out each one (profiler output, logs, a reproduction). This shows your reasoning, not just the ending.
- Explain the fix you chose over at least one alternative and why, including the trade-off you accepted (complexity, cost, a migration risk).
- Close with a number (latency, error rate, run time, incidents) and what you added so it cannot recur: a test, an alert or a runbook.
Follow-up
- Which alternative did you reject, and what would have made it the right choice?
- How did you verify that your change, and not something else, fixed the problem?
- What would you monitor today to catch the same problem earlier?
What version control systems are you familiar with, and how do you use them in your workflow?
Medium · Technical / Domain Questions
Approach
- Name the systems you have actually used (Git above all, and Subversion or TFVC if true). Then describe a real loop: a short-lived feature branch off main, small commits, a pull request with review and CI checks, and a merge once it is green.
- Compare branching models. Trunk-based development with feature flags keeps integration continuous. GitFlow's develop and release branches suit scheduled releases but cause long-lived divergence and painful merges.
- Explain merge versus rebase. Rebasing a local feature branch keeps history linear. Never rewrite history that others have pulled, and if a force push is unavoidable on your own branch, use --force-with-lease.
- Show the recovery tools. git revert undoes a pushed commit safely with a new commit. git reset is for local history only. git bisect finds the commit that introduced a regression in O(log n) test runs. git reflog recovers lost commits.
- Mention commit hygiene: atomic commits, messages that explain why, tags for releases, and resolving conflicts by understanding both sides rather than taking one wholesale.
Follow-up
- A bad commit is already on the shared main branch. How do you undo it?
- When is rebasing dangerous, and what does --force-with-lease protect against?
- How would you use git bisect to find when a test started failing?
Given a specific scenario, how would you design a solution to optimize performance?
Medium · Problem-Solving / Case Studies
Approach
- Pin down the scenario before designing anything: which operation is slow, the metric (p95/p99 latency or throughput), current and expected load, and the target. For example, a page listing a borrower's payment history that takes seconds under load.
- Measure where the time goes: application profiling, distributed traces and database query plans (EXPLAIN). Most slow request paths turn out to be database or network bound, not CPU bound.
- Apply fixes by layer. In the database: indexes matching the WHERE and ORDER BY, removing N+1 queries, pagination. Above it: a cache-aside cache with a TTL and explicit invalidation. Move non-interactive work (statements, notifications) to a queue and background workers. Scale stateless services horizontally behind a load balancer.
- State the trade-offs. Caching and read replicas serve stale data, which is acceptable for reference data but not for a balance or payment status read right after a write. Every queue and cache layer adds operational complexity.
- Verify with a load test at the same traffic before and after, compare percentiles rather than averages, and add an alert on the metric you improved.
Follow-up
- How do you keep the cache correct when the underlying record changes?
- Indexing did not help enough and the database is still the bottleneck. What next, and what does replication lag cost you?
- How do you show the improvement came from your change and not from lower traffic?
How would you assess the trade-offs between different architectural decisions?
Medium · Problem-Solving / Case Studies
Approach
- Start from requirements and quality attributes: latency, throughput, consistency, availability, cost, auditability or regulatory needs, and what the team can operate. A decision is only good relative to these.
- Compare concrete options in a small matrix. Monolith or microservices: independent deploys and scaling against network failures, distributed transactions and operational overhead. Relational or NoSQL: ACID transactions and joins against horizontal scale and schema flexibility. Synchronous REST or asynchronous messaging: simplicity against decoupling and resilience.
- Tie it to failure behaviour. Under a network partition a distributed store must choose consistency or availability (CAP). Money movement and account balances usually need strong consistency and idempotent operations.
- Weigh reversibility. Spend analysis on decisions that are expensive to undo (data model, service boundaries) and decide cheap ones quickly. Run a spike or prototype to test the riskiest assumption.
- Record the decision and its rejected alternatives in an architecture decision record so it can be revisited when the constraints change.
Follow-up
- When would you split a monolith, and what would you extract first?
- How do you keep two services consistent without a distributed transaction (outbox pattern, sagas, idempotency keys)?
- Tell me about an architectural decision you would reverse now, and why.
Walk us through your thought process in developing a new feature for an existing application.
Medium · Problem-Solving / Case Studies
Approach
- Clarify the requirement and the acceptance criteria with the product owner, including edge cases, permissions, and any audit or compliance needs, before touching code.
- Read the existing code: find the integration points, the conventions and the current tests. Follow existing patterns unless there is a reason to break them, and say what that reason is.
- Design for a safe change. Make schema changes backward compatible (expand, migrate, then contract), make API changes additive or versioned, and keep the feature behind a flag so it can ship dark.
- Deliver in small reviewable pull requests with unit and integration tests. If the code you touch has no tests, add characterization tests first.
- Roll out gradually, watch error rates and usage, then remove the flag and the dead code paths.
Follow-up
- How do you rename or change a column that running code still reads, without downtime?
- The module you need to change has no tests. Where do you start?
- How do you estimate this feature when you do not know the codebase yet?
How do you ensure quality and maintainability in your code?
Medium · Problem-Solving / Case Studies
Approach
- Automate the safety net. A test pyramid (many fast unit tests, fewer integration and end-to-end tests) runs in CI on every pull request, and a red build blocks the merge.
- Keep pull requests small and reviewed. In review I look for correctness, edge cases, naming, and whether the change will be easy for someone else to modify, not just for style.
- Let tools enforce style and catch simple bugs: formatters and linters (Prettier/ESLint, ruff or pylint, Roslyn analyzers, Checkstyle/SpotBugs) and static analysis such as SonarQube.
- Apply design habits that reduce coupling: single-responsibility functions and classes, dependency injection so code can be tested, clear names, and comments that explain why rather than what.
- Manage technical debt deliberately: refactor under test coverage, track debt items, and treat coverage as a signal, not a target, since high coverage with weak assertions proves little.
Follow-up
- What is the first thing you check when reviewing a teammate's pull request?
- How do you decide between refactoring now and shipping on a deadline?
- When is a high coverage number misleading?
Describe your approach to debugging a complex issue in production.
Medium · Problem-Solving / Case Studies
Approach
- Contain the impact first. Assess how many users or transactions are affected. If a recent deploy or config change lines up with the start, roll it back or switch off the feature flag before you look for the root cause.
- Build a timeline of what changed: deploys, config, data volume or shape, traffic, and dependency health. Then read logs (by correlation or request ID), metrics and traces around the first bad event.
- Narrow down systematically. Reproduce in a lower environment with production-like data, or bisect across commits, flags or input subsets so that each check rules out half of the candidates.
- Check the instrumentation before trusting the symptom (a missing metric, sampling, clock skew), and separate the trigger from the underlying cause.
- Fix the cause, add a regression test and an alert that would have caught it earlier, and write a blameless postmortem with follow-up actions.
Follow-up
- The issue happens about once a day and you cannot reproduce it locally. What do you do?
- How do you tell a real cause from a coincidence in the timeline?
- When would you not roll back, even though a deploy lines up with the incident?
Suggested practice checklist
The plan follows the two reported rounds: first your story bank and the manager conversation, then language fundamentals, coding, debugging and design reasoning for the panel, and a closing rehearsal of both. Each day points at the reported questions it practises.
Day 1 — Map the loop and build your story bank
- Write the two reported rounds (manager behavioral interview, developer panel technical interview) and list which of your skills each round relies on.
- Write a short career summary with a specific reason for wanting a software role in financial services.
- Write four stories in situation, action, result form, each naming a decision you personally made.
Deliverable: A one-page loop map, a career summary and four written stories that the later behavioral days draw on.
Day 2 — Language fundamentals: async, memory, version control
- Explain synchronous versus asynchronous programming aloud with a code example in your language (a blocking call versus a callback, future or async function).
- Write a one-page memory-management explanation for your language covering allocation, collection, a leak example and how you would diagnose it.
- Write out your Git workflow: branching, pull requests, resolving a merge conflict and undoing a bad commit.
Deliverable: Three spoken or written explanations, one per task, each with an example from real work.
Day 3 — Coding: strings, sorting and searching, data structures
- Write a string reversal two ways (new string and in place on a character array) and state complexity and edge cases for each.
- Implement merge sort and quicksort, and write binary search, then list the deciding property for each sort (stability, memory, worst case).
- Implement a linked list and a hash map, or another structure you choose, with the core operations and complexity for each.
Deliverable: Working code for the reversal, two sorts, binary search and your chosen data structure, with a complexity note on each.
Day 4 — Testing, code quality and performance habits
- Write unit tests for one of yesterday's functions, including edge cases, and practise a red, green, refactor cycle on a new function.
- Write a checklist for maintainable code: naming, small functions, review habits, documentation, automated checks.
- Profile or reason about one slow function and write down three optimizations with the measurement that would justify each.
Deliverable: A test file, a code-quality checklist and a short list of three measured optimizations.
Day 5 — Production issues, performance and design trade-offs
- Rehearse a production-debugging answer as a fixed sequence and apply it to one real incident from your past.
- Choose two architectural decisions you have made and write each as options, trade-offs and your reasoning.
Deliverable: A debugging answer outline, notes from the two SQL exercises and two written trade-off comparisons.
Day 6 — Behavioral answers out loud
- Say aloud, in situation, action, result form, your answers on pressure, conflict, competing deadlines and initiative.
- Prepare a two-part answer on values: two or three values, each with a behavior and an example with a cost.
- Write up an API integration you built (mechanics, error handling, testing), a challenging technical problem you solved, and how you would add a feature to an existing application.
Deliverable: Spoken versions of five behavioral answers, a values answer, and written outlines of the API, technical-problem and feature stories.
Day 7 — Full rehearsal of both rounds
- Run the manager round start to finish aloud: career summary, motivation, two stories and your own questions for the manager.
- Run a technical round: one language fundamentals question, one coding problem written by hand and one debugging scenario.
- Review your weakest answer from the week and rewrite it.
Deliverable: One recorded or written rehearsal for each round and a rewritten weakest answer.
Behavioral preparation for the manager round
The first round is a manager conversation about your background, motivations and fit for the role, and the reported behavioral prompts cover pressure, conflict, competing deadlines, initiative and values. For a Software Engineer, build each story around a decision you made and what changed afterwards, and keep a technical example (a defect, an integration, a release) ready for each theme.
How do you handle memory management in your preferred programming language?
Medium · Technical / Domain Questions
Approach
- Choose the language you will code in and explain memory from the runtime up. Say where values live (stack versus heap) and who releases them. In Java and C# a tracing, generational garbage collector reclaims unreachable objects, collecting short-lived ones cheaply and promoting survivors. In Python, reference counting frees most objects immediately and a cycle collector handles reference cycles.
- Say what you still own in a managed language. A leak means an object stays reachable longer than needed: a static map or cache with no eviction, a listener never unregistered, a thread-local never cleared. Non-memory resources (files, sockets, database connections) need deterministic release: try-with-resources in Java, using or IDisposable in C#, a with block in Python.
- Describe how you diagnose a problem. Watch heap use after collections and look for a rising baseline, take a heap dump or snapshot (a profiler, a dump tool, or tracemalloc in Python) and follow the retaining path of the largest object group. Fix the cause, for example bound the cache or stream the input, rather than raising the heap limit.
- Name the trade-off. Garbage collection buys safety and productivity at the cost of pause times and less predictable freeing. Reducing allocation (reusing buffers, avoiding needless copies, streaming large files) is a measured optimization, not a default.
- This question is filed among the behavioral prompts but it is a technical explanation. Add one real example if you have it, such as a leak you found and how you confirmed it was gone.
Follow-up
- What are the common causes of a memory leak in a garbage-collected language?
- How does Python deal with two objects that reference each other?
- How would you process a file that is larger than the memory available?
Discuss your experience with APIs and how you have integrated them into applications.
Medium · Technical / Domain Questions
Approach
- Pick one integration you built or maintained and open with its shape: what the API was (for example REST with JSON), whether you called someone else's API or exposed your own, and what business function it served. Two or three sentences is enough; the detail comes next.
- Walk through the mechanics a reviewer would want to see: authentication (API keys, or OAuth2 with token refresh), a timeout on every call, retries with exponential backoff and jitter only when the request is safe to repeat (or carries an idempotency key), handling of rate limits such as a 429 with a Retry-After header, and pagination for large result sets.
- Explain how you isolated it. A thin client or adapter class kept the external format out of the rest of the code, mapped provider errors to your own error types, and let tests use a fake or recorded responses instead of the live service. Mention contract tests or schema validation if you used them.
- Cover operating it: logging with a correlation id and without sensitive fields such as account numbers, a circuit breaker or fallback for outages, alerts on error rates, and how you coped with a version change on the provider side.
- Finish with the result and one lesson, such as fewer failed calls after adding idempotency keys. Quote a number only if it is true.
Follow-up
- How did you prevent a retried request from being applied twice?
- What did you do when the provider changed a response format without warning?
- How did you test the integration without calling the real service?
Describe a time when you had to work under pressure. How did you handle it?
Medium · Behavioral / Leadership Questions
Approach
- Choose a situation with a real constraint, such as a release date, a production incident or a sudden change in scope, where you were personally responsible for an outcome. State it in two or three sentences: what was at stake and by when.
- Spend most of the answer on actions in order: how you triaged and listed what must ship versus what could wait, what you cut or deferred and who agreed, how you told your manager and stakeholders early, and which quality checks (tests, code review) you kept.
- Show how you stayed effective: broke the work into small verifiable steps, asked for help on the riskiest part, and avoided changes you could not test.
- Close with the result, the cost you knowingly accepted, and what you changed afterwards (an alert, a runbook, a better estimate). The story fails if it is only 'I stayed calm and worked long hours' with no decisions in it.
Follow-up
- What did you decide to cut, and who agreed to it?
- What would you do differently if the same situation came up again?
- What if you had realised you could not make the date?
Can you provide an example of how you resolved a conflict within your team?
Medium · Behavioral / Leadership Questions
Approach
- Choose a real disagreement with a named kind of person (a peer, a reviewer, a product manager) about something that mattered: an approach in code review, a design choice, a deadline. Avoid a conflict that was just a personality clash with no work at stake.
- Present both positions fairly in a sentence each, including the other person's legitimate constraint. Then describe what you did: spoke to them directly and privately first, asked questions to understand their reasoning, and moved the discussion to evidence such as a quick prototype, a benchmark, a test case or a written comparison.
- Say how it was decided: an agreed criterion, a trial period, or escalation to a manager only after the two of you could not settle it. Show that you were willing to be the one who changed your mind if the evidence went the other way.
- Finish with the outcome and the working relationship afterwards. The mistake that sinks this answer is casting the other person as the problem or telling a story where you simply won.
Follow-up
- What did you do when the other person still disagreed after seeing the evidence?
- At what point did you involve your manager, and why then?
- What would you do differently now?
How do you prioritize tasks when you have multiple deadlines?
Medium · Behavioral / Leadership Questions
Approach
- Lead with the method, then prove it with a real example. List every commitment with its deadline, who is waiting on it, the impact of missing it and a rough size. Order by deadline risk and by what blocks other people, not by what is easiest or most recent.
- Give a concrete case with three competing items, for example a production defect, a feature due this week and a pending code review. Say what you did first, what you deferred and what you told each requester.
- Show that you communicate trade-offs in writing: ask the requester or your manager which item can slip when two collide, confirm the new order, and re-plan visibly when priorities change mid-sprint.
- Mention how you protect the plan, for instance by splitting large tasks into pieces that can ship independently and by flagging risk as soon as an estimate moves. Avoid claiming that you do everything; the answer is about choosing.
Follow-up
- What do you do when two managers each say their deadline comes first?
- How do you handle a priority change halfway through a sprint?
- How do you say no or not yet to a request, and what do you offer instead?
Discuss a situation where you took the initiative on a project.
Medium · Behavioral / Leadership Questions
Approach
- Pick a gap nobody owned that you noticed and acted on without being asked: a flaky test suite, a manual deploy step, missing documentation for a fragile module, or a recurring defect with no owner. Make clear it was outside your assigned tasks.
- Describe how you scoped it small first, such as a one-day proof, and how you got buy-in from your team or manager before investing more, including how you protected your regular commitments.
- Describe what you built or changed, how you measured the effect (failures per week, time saved per release, defects avoided), and how you handed it over so it did not depend on you alone.
- The mistake is an example of initiative that bypassed the team, or one that was simply your assigned job. Name what you learned or what you would do differently.
Follow-up
- How did you persuade others that it was worth the time?
- What did you do when it was not working as planned?
- Who maintained it after you moved on?
What values do you believe are important for a software engineer to uphold?
Medium · Behavioral / Leadership Questions
Approach
- Choose two or three values and tie each to a behavior you can show, since a list of words says little. Good candidates for a software engineer include owning correctness (tests and ownership of defects), honesty about risk and mistakes, and respect for teammates through code review and clear communication.
- Support each value with a short example from your work: the time you raised a defect you had introduced before anyone noticed, or the review comment you wrote that taught someone something without blocking them.
- Candidates report that the work involves financial services and regulatory requirements. Care with customer data, traceable changes and honest reporting are natural values to illustrate, as long as your examples are real.
- Say what the value costs you: a slower merge, an awkward conversation, a deadline conversation raised early. The mistake is naming values that sound good with no cost attached.
Follow-up
- Tell me about a time you upheld one of those values when it was inconvenient.
- What would you do if a teammate was cutting corners on testing?
- How do those values show up in how you review code?