Interview guides · Ascendion
Ascendion Software Engineer Interview Guide
Ascendion Software Engineer interview guide: six reported rounds, OOP, SOLID, SQL and live coding questions, a 7-day plan and behavioral prep.
The 60-second brief
Candidates describe Ascendion as a digital engineering company whose engineers build software for enterprise clients: cloud-native platforms, modernisation of older applications and larger digital transformation programmes. The client domains reported range from financial services and healthcare to high-tech and enterprise software. A Software Engineer on these engagements is described as working across backend services, user interfaces and cloud services, designing microservices and both relational and non-relational data models, and writing unit and integration tests. The stacks listed for the role are Python, Java with Spring Boot, C# with .NET Core, React and Node.js, so the day-to-day language depends on the client account you are placed on.
This guide is for candidates interviewing for a Software Engineer position at Ascendion, from associate level to senior developer. It covers the six reported rounds, the reported technical questions (OOP and language fundamentals, strings and matrices, SQL and persistence, REST, Spring Boot or .NET Core, microservice messaging, React or Vue state, SPA performance) and the scenario questions about bugs, priorities, disagreements, career goals and unfamiliar codebases. It ends with a seven-day plan.
Candidates report six rounds over roughly 4-6 weeks: an online assessment, a recruiter screening call, L1 and L2 technical interviews, a client interview for client-facing roles, and a managerial and HR discussion. Some reports describe a shorter pipeline when no client round applies.
Focus areas
- Object-Oriented Programming (OOP)
- DSA (Data Structures and Algorithms)
- SQL
Overview
The reported questions fall into five groups. First, object-oriented and language fundamentals: the four pillars, overloading versus overriding, SOLID with dependency inversion, constructors, abstract classes versus interfaces, and static versus instance members. Second, practical coding: reversing a string without library helpers, counting character frequencies, finding repeated characters, matrix traversal or rotation, and palindrome checks. Third, frameworks and services: REST methods and status codes, Spring Boot or .NET Core architecture and dependency injection, synchronous versus asynchronous communication between microservices, SPA load performance, and React or Vue state management. Fourth, databases: JOIN types, slow-query diagnosis, clustered versus non-clustered indexes, Java collections and HashMap internals, and Hibernate or Entity Framework behaviour. Fifth, scenario questions about bugs, priorities, disagreements, leaving a previous employer and legacy code. Candidates describe the overall difficulty as average to moderately challenging, with the weight on fundamentals.
Candidates say the questions follow your primary stack: Java, .NET, Python or full-stack JavaScript. The requirements they describe call for one main language (Java, C#, Python, JavaScript/TypeScript or C++), solid OOP and SOLID, SQL with JOINs, familiarity with Spring Boot, .NET Core, Node.js or React, and Git. Cloud platforms, Docker, Kubernetes, Kafka, RabbitMQ and CI/CD are listed as nice-to-have. Pick one stack and go deep, then learn the equivalent names on the other side, because several reported questions say 'Java or C#' or 'Hibernate or Entity Framework'. Less common topics reported are generics, reflection, thread safety, the Saga pattern, circuit breakers, graph traversal, dynamic programming, sharding and MongoDB. Cover the basics first and treat these as extras.
Two reported questions are filed under scenario questions but are technical in substance: cleaning null values with Pandas and NumPy, and managing state across a React or Vue component tree. Prepare them as technical answers with code and trade-offs. Candidates also report example prompts such as a SQL query for the second highest salary, a diagonal sum over a matrix, securing REST APIs with OAuth 2.0 and JWT, a microservice design for high-throughput financial transactions, and custom exception handling in Java or C#. Practise these alongside the question list.
Candidates report that technical panels read the resume line by line and that engineers are placed on client engagements, so project narration and clear speech carry weight next to code. For every project you list, prepare your own role, the design and database choices, the deployment path and one optimisation. Reported live coding happens on an empty IDE or notepad, so rehearse without autocomplete and clarify inputs, outputs and edge cases before you type.
The Ascendion interview process
The six stages below are the order and names candidates report, with 4-6 weeks end to end in the headline summary. Treat the client interview as applying to client-facing roles, and expect your recruiter to confirm which stages your track includes.
Online Assessment
Candidates describe this stage as an initial assessment of foundational technical competence. Some tracks are reported to use third-party screening platforms or recorded video early in the pipeline, so find out from your recruiter which format you have. No question count or format beyond that is reported, so prepare for the fundamentals that recur across the loop: OOP, data structures and algorithms, SQL and, for some candidates, C#. Do timed practice in your main language on basic string and array problems, and refresh the OOP, SOLID and JOIN material before the link arrives.
What to demonstrate
- Foundational technical competence, as the stage is described
- Working command of basics in your primary language
- Fluency with OOP, DSA and SQL, the topics candidates report most across the loop
How to prepare
- Solve basic string and array problems in your main language under a timer, with no autocomplete.
- Revise the four OOP pillars, SOLID, and the four JOIN types so short conceptual answers are automatic.
- If your track uses a recorded or proctored platform, test camera, microphone and connection beforehand, and practise answering aloud in a clear, steady voice.
Recruiter Screening Call
Candidates describe a conversation with a recruiter to assess role-specific alignment. Questions candidates report that fit a screening call include why you left your previous organisation and how your technical goals fit Ascendion. Use the call to state your primary stack plainly (Java, .NET, Python or full-stack JavaScript), because later questions are reported to follow it, and to learn which of the later rounds your track includes.
What to demonstrate
- Fit between your experience and the role's stack
- Clear spoken communication about your background
- Motivation for moving, as the reported career-goals question suggests
How to prepare
- Write a two-minute walk through your resume organised by technology and project, ending with the stack you want to work in.
- Prepare a neutral, forward-looking answer to why you are leaving, and a specific reason for choosing client-facing engineering work.
- Ask which rounds apply to your track, whether a client interview is included, and how the engagement works, since one candidate review asks for clearer communication about contractual roles.
L1 Technical Interview
Candidates describe the first technical interview as covering core programming and framework questions. Reports mention rapid-fire conceptual questions as well as architecture discussion about frameworks, APIs and ORMs. The reported question types here include OOP and language mechanics, REST, Spring Boot or .NET Core with dependency injection, and database basics. Give short, correct definitions followed by a concrete example from your own code, and say so plainly when you do not know a detail, then reason from the principle.
What to demonstrate
- Core programming knowledge in your primary language
- Framework mechanics: REST, dependency injection, annotations or attributes
- Ability to explain concepts concisely and concretely
How to prepare
- Rehearse the OOP and SOLID answers aloud with one example each from a service-layer class you have written.
- Be able to explain stack versus heap, garbage collection and reference types, and what static members share across instances.
- Sketch the request flow of a Spring Boot or .NET Core Web API from controller to repository, and explain how dependency injection wires the pieces.
L2 Technical Interview
Candidates describe the second technical interview as focused on live coding and database management. Live coding is reported to take place on an empty IDE or notepad, with strings, arrays, matrices and basic data structure implementations as typical material, and SQL covering JOINs, aggregations, subqueries, indexing and execution plans. Confirm input types, outputs and edge cases before writing, speak your reasoning while you code, then walk your solution through a small test case.
What to demonstrate
- Working code for fundamentals such as strings, arrays and matrices
- Edge-case handling and the clarity of your reasoning while coding
- Database skills: query writing, indexes and slow-query reasoning
How to prepare
- Write string reversal, palindrome and character-frequency solutions in a plain editor, then state time and space complexity for each.
- Practise matrix rotation, diagonal sum and path-finding on grids, including non-square and one-cell inputs.
- Write the second-highest-salary query in more than one way, a three-table JOIN with aggregation, and explain which index each query would use.
Client Interview
Candidates describe a client interview aimed at validating project fit and communication, reported for client-facing roles and roles deployed on direct enterprise accounts, after the internal L1 and L2 rounds. Candidates describe its focus as project alignment and situational problem-solving. Expect to explain what you built, how you decided, and how you would handle an operational issue, in language a client stakeholder can follow.
What to demonstrate
- Match between your project experience and the client's work
- Communication with a non-internal audience
- Situational problem-solving on technical hurdles
How to prepare
- Write a short summary of your two strongest projects: problem, your own contribution, stack, one trade-off and one measurable result.
- Practise explaining a technical decision (for example messaging versus direct REST calls) to someone who is not an engineer.
- Prepare your bug-diagnosis story and your answer on getting up to speed in an unfamiliar legacy application, as both fit client engagements.
Managerial and HR Discussion
Candidates describe the final stage as a managerial and HR discussion, where compensation and onboarding details are settled. Candidate advice for managerial and behavioural questions is to answer in STAR form with personal contributions and quantified outcomes. Expect questions drawn from the scenario list: priorities and changing requirements, disagreements, and career goals.
What to demonstrate
- Behavioural answers that show your own contribution
- Readiness for onboarding onto a client engagement
- Clarity on logistics such as notice period and location
How to prepare
- Write STAR outlines for the priorities, disagreement and bug stories, each with a number in the result.
- Know your notice period, location constraints and expectations before the call, and have onboarding questions ready.
- Repeat your reason for choosing this role consistently with what you told the recruiter.
Where candidates lose points
Listing technologies on the resume that you cannot defend in detail
Candidates report line-by-line scrutiny of listed projects, technologies and team roles. For each item, prepare your own role, one design or database decision, one trade-off and one thing that went wrong. Cut anything you could not discuss for several minutes.
Reciting OOP and SOLID definitions with no example
Attach one concrete example from a service layer to each answer: a repository interface injected into a service so tests can substitute a fake, an overridden method chosen at runtime versus an overloaded one chosen at compile time, a class split because it had two reasons to change.
Starting to code a string or matrix problem without pinning down the inputs
Confirm input type, expected output and edge cases first, then test with them: empty string, single character, repeated characters, palindrome with spaces or mixed case, negative numbers, a one-cell or non-square matrix. State time and space complexity when you finish.
Answering SQL from memorised syntax and missing the traps
For second-highest salary, handle ties, nulls and tables with fewer than two rows. Check whether a JOIN is one-to-many before aggregating. For a slow query, read the execution plan before proposing an index, and explain clustered versus non-clustered storage.
Behavioural answers that say 'we' throughout, or criticise a former employer
Use STAR with a clear 'I' for your own actions and a number in the result. For why you left, name a neutral reason and spend the answer on what you want next.
Questions & practice
Explain the four pillars of Object-Oriented Programming (OOP) and how you apply them in real-world application
Medium · Object-Oriented Programming & Core Langu
Explain the four pillars of Object-Oriented Programming (OOP) and how you apply them in real-world application design.
Approach
- Encapsulation: keep fields private and change state only through methods that enforce the invariant, e.g. an Account whose balance moves only through deposit() and withdraw(), and both reject negative amounts.
- Abstraction: callers depend on what a component does, not how it does it. A PaymentGateway interface with charge() hides whether the implementation calls one provider or another.
- Inheritance models an is-a relationship and reuses base behaviour. Prefer composition when the relationship is has-a or behaviour must change at runtime, because deep hierarchies make base-class changes break subclasses.
- Polymorphism comes in two forms. Compile-time polymorphism is overloading. Runtime polymorphism is overriding called through a base reference: a List<NotificationSender> holding Email and Sms senders replaces a switch on type.
- Close with one class from your own project for each pillar. A definition with no applied example reads as memorised.
Follow-up
- When has inheritance caused you problems, and how would composition have changed the design?
- What is the difference between encapsulation and abstraction, since both hide something?
- Show runtime polymorphism in code with a collection of base-class references.
What is the difference between method overloading and method overriding in Java or C#? Give concrete examples.
Medium · Object-Oriented Programming & Core Langu
Approach
- Overloading means the same method name with a different parameter list (count, types or order) in one class. The compiler picks the overload at compile time from the static types of the arguments. A different return type alone does not make a valid overload.
- Overriding means a subclass supplies its own body for an inherited instance method with the same signature. The JVM or CLR picks the body at runtime from the object's actual type: Shape s = new Circle(); s.draw() runs Circle.draw().
- Java rules: non-private, non-static, non-final instance methods are virtual. @Override catches signature typos, return types may be covariant, visibility cannot narrow, and the override cannot throw broader checked exceptions.
- C# rules: the base method must be virtual, abstract or override, and the subclass uses override. Using new instead hides the method, so the call is resolved from the variable's static type. sealed override stops further overriding.
- Edge cases: static methods are hidden, not overridden. In Java, overload resolution prefers widening over boxing over varargs, so print(long) beats print(Integer) for an int argument.
Follow-up
- If two overloads take Object and String and you pass a String through an Object-typed variable, which one runs, and why?
- Can you override a static or private method? What happens if you try?
- In C#, what does a caller see when a subclass uses new instead of override?
What are the SOLID principles? Explain the Dependency Inversion Principle and how it improves application test
Medium · Object-Oriented Programming & Core Langu
What are the SOLID principles? Explain the Dependency Inversion Principle and how it improves application testability.
Approach
- Name all five, each with a one-line test. SRP: a class has one reason to change. OCP: add behaviour through new implementations instead of editing tested code. LSP: subtypes must honour the base contract (the Square/Rectangle setter problem). ISP: several small role interfaces instead of one fat one.
- DIP: high-level policy and low-level details both depend on an abstraction. OrderService depends on an OrderRepository interface rather than SqlOrderRepository, and gets the concrete class through its constructor.
- Testability: in a unit test, pass a fake or a Mockito/Moq mock of the repository. The test then needs no database, runs fast, and can force failure paths such as a timeout or a duplicate key.
- Keep the terms apart. DIP is the principle, dependency injection is the technique of supplying dependencies from outside, and an IoC container (Spring's ApplicationContext, .NET's IServiceCollection) automates the wiring.
- Trade-off: an interface for every class adds indirection for no benefit. Put abstractions at real seams such as I/O, external APIs, the clock and randomness.
Follow-up
- Give an LSP violation you have seen in real code and how you fixed it.
- Constructor injection or field injection: which do you use, and why?
- How would you unit-test a method that calls System.currentTimeMillis() or DateTime.Now directly?
Explain the purpose of constructors, abstract classes, and interfaces. When would you choose an interface over
Medium · Object-Oriented Programming & Core Langu
Explain the purpose of constructors, abstract classes, and interfaces. When would you choose an interface over an abstract class?
Approach
- A constructor puts a new object into a valid state. It has no return type, can be overloaded and chained (this(...) in Java, : this(...) in C#), and always runs the superclass or base constructor first. The compiler adds a default constructor only if you declare none.
- An abstract class cannot be instantiated. It can hold fields, constructors, implemented methods and abstract methods. A class extends at most one class in both Java and C#.
- An interface is a contract, and a class can implement many. Java 8 added default and static methods and Java 9 added private methods. C# 8 added default interface members. Interfaces still hold no per-instance state.
- Choose an interface when unrelated classes share a capability (Comparable, IDisposable), when a class needs several types, or when you want a seam for DI and mocking. Choose an abstract class when subclasses share state and a template-method skeleton.
- Common trap: abstract classes do have constructors. They run through subclass constructor chaining and initialise the shared fields.
Follow-up
- Can an abstract class have a constructor, and when does it run?
- If two interfaces supply the same default method, how does Java make the implementing class resolve it?
- Why not make every base type an abstract class?
How do static methods and variables differ from instance methods and variables in terms of memory execution?
Medium · Object-Oriented Programming & Core Langu
Approach
- Static fields belong to the class, so there is one copy per loaded class. Instance fields belong to each object and are allocated on the heap with every new call. Local variables and references live in the calling thread's stack frame.
- Java detail: since Java 8, class metadata lives in Metaspace (PermGen is gone), and in HotSpot the static field values sit with the class's Class object on the heap. Method bytecode is stored once per class for both static and instance methods.
- The real difference between the methods is dispatch and context. An instance method receives an implicit this and is dispatched virtually. A static method has no this, cannot touch instance members directly, and is bound at compile time.
- Lifetime: a static field lives as long as its class is loaded and acts as a GC root. A static cache or list that only grows is a classic memory leak in a long-running service.
- Concurrency: static mutable state is shared by every thread and request. A static counter needs AtomicInteger, Interlocked or synchronisation, while instance state confined to one request needs none.
Follow-up
- Why can't a static method call an instance method without an object?
- Where does a local variable declared inside a static method live?
- How would you find and fix a memory leak caused by a static collection?
Write a program to reverse a string without using built-in library functions.
Medium · Practical Coding, Algorithms & Data Stru
Approach
- Clarify first: return a new string or reverse in place, how to treat null or empty input, and whether the input is ASCII or arbitrary Unicode. Java and C# strings are immutable, so you work on a char array.
- Two pointers: i = 0 and j = n - 1, swap chars[i] and chars[j], then move both inward while i < j. That is O(n) time and O(1) extra space beyond the array copy.
- Avoid result = result + s[i] in a loop. Each concatenation copies the string, so the loop is O(n^2). Fill a preallocated char array from the back instead.
- Test null, empty, a single character, and both odd and even lengths. Reversing UTF-16 code units splits surrogate pairs such as emoji, so reverse by code point if full Unicode matters.
- A recursive version works, but it uses O(n) stack depth and can overflow on long input. Say so if you offer it.
Follow-up
- Reverse the order of words in a sentence while keeping each word's letters in order.
- How would you reverse a string that contains emoji or combining accents correctly?
- Reverse only the vowels, or only the letters, leaving other characters in place.
Given a string, write an algorithm to count character frequencies or find repeated characters using streams or
Medium · Practical Coding, Algorithms & Data Stru
Given a string, write an algorithm to count character frequencies or find repeated characters using streams or dictionary mappings.
Approach
- Count in one pass with a hash map from character to count: O(n) time and O(k) space for k distinct characters. For plain ASCII, an int[128] array indexed by the char is faster and simpler.
- For repeated characters, either keep the counts greater than 1, or find the first repeat with a set: Java's Set.add and C#'s HashSet.Add both return false when the element is already present.
- Order matters when output is printed. Use LinkedHashMap in Java to keep first-seen order. Python dicts keep insertion order (3.7+) and Counter does the counting. C# Dictionary enumeration order is not guaranteed.
- Java streams version: s.chars().mapToObj(c -> (char) c).collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting())) returns Map<Character, Long>. In C# LINQ: s.GroupBy(c => c).Where(g => g.Count() > 1).Select(g => g.Key).
- Ask about case sensitivity, spaces and punctuation, and Unicode before coding. Test an empty string, all-identical characters and no repeats.
Follow-up
- Return the first non-repeating character. What changes in your solution?
- Check whether two strings are anagrams using the same counting idea.
- If the input were a stream too large for memory, how would you report the k most frequent characters or words?
Solve a two-dimensional matrix traversal problem (e.g., finding paths or rotating a matrix).
Medium · Practical Coding, Algorithms & Data Stru
Approach
- Rotate an n x n matrix 90 degrees clockwise in place: transpose (swap m[i][j] with m[j][i] for j > i), then reverse each row. That is O(n^2) time and O(1) extra space. For counter-clockwise, transpose and then reverse the row order.
- A non-square m x n matrix cannot be rotated in place. Allocate an n x m result and set result[j][m-1-i] = a[i][j].
- Path counting with right and down moves only: dp[i][j] = dp[i-1][j] + dp[i][j-1], with obstacle cells set to 0. That is O(mn) time, and one rolling row cuts space to O(n). For reachability or shortest path in four directions, run BFS with a visited grid.
- Spiral order keeps four boundaries (top, bottom, left, right) and shrinks one after each pass. Re-check top <= bottom and left <= right before the return passes, or a single row or column prints twice.
- Diagonal sum: add m[i][i] + m[i][n-1-i] and subtract the centre once when n is odd. Always test the empty matrix, a 1 x n matrix and jagged rows.
Follow-up
- Rotate by 180 degrees, or counter-clockwise, without extra space.
- Count the islands of 1s in a grid, and give the complexity.
- Print the spiral order of a non-square matrix. Which boundary checks change?
Write a program to check whether a given string or number is a palindrome.
Medium · Practical Coding, Algorithms & Data Stru
Approach
- For a string, compare characters with two pointers moving inward from both ends and stop at the first mismatch: O(n) time, O(1) space. Building a reversed copy also works but costs O(n) memory.
- Clarify the rules first. Is the check case-insensitive, and are punctuation and spaces ignored as in 'A man, a plan, a canal: Panama'? If so, skip characters that fail Character.isLetterOrDigit or char.IsLetterOrDigit and compare lowercase.
- For a number, build the reverse arithmetically with rev = rev * 10 + x % 10. Negative numbers are not palindromes, and neither is any number ending in 0 except 0 itself.
- To avoid overflow, reverse only half the digits. Loop while x > rev, then return x == rev || x == rev / 10, where the second case handles odd digit counts.
- Edge cases: null, empty string, a single character, and even versus odd length.
Follow-up
- Find the longest palindromic substring. What does expand-around-centre cost?
- Can the string become a palindrome by deleting at most one character?
- Check whether a singly linked list is a palindrome using O(1) extra space.
Explain the different types of SQL JOINs (Inner, Left, Right, Full) and write a query to join multiple relatio
Medium · Databases, SQL & Data Persistence
Explain the different types of SQL JOINs (Inner, Left, Right, Full) and write a query to join multiple relational tables.
Approach
- INNER JOIN returns only matching rows. LEFT JOIN keeps every left row and fills NULLs where nothing matches. RIGHT JOIN is the mirror image, usually rewritten as a LEFT JOIN. FULL OUTER JOIN keeps unmatched rows from both sides; MySQL lacks it, so you emulate it with a LEFT JOIN UNION a RIGHT JOIN. Also know CROSS and self joins.
- Multi-table example: customers c LEFT JOIN orders o ON o.customer_id = c.id LEFT JOIN order_items oi ON oi.order_id = o.id, GROUP BY c.id, c.name, selecting COUNT(DISTINCT o.id) and COALESCE(SUM(oi.quantity * oi.unit_price), 0).
- Trap: a filter on the right-hand table in WHERE (WHERE o.status = 'PAID') removes the NULL rows and turns the LEFT JOIN into an inner join. Put that condition in the ON clause to keep customers with no paid orders.
- Fan-out: joining two one-to-many children (say orders and payments) multiplies rows and inflates sums. Aggregate each child in a CTE or subquery first, then join the results.
- Anti-join for 'customers with no orders': use LEFT JOIN ... WHERE o.id IS NULL, or NOT EXISTS. NOT IN returns no rows if the subquery yields a NULL.
Follow-up
- Write the second-highest salary from an Employee table. How do you handle ties and a table with one row?
- What is the difference between putting a condition in ON and in WHERE for a LEFT JOIN?
- Your SUM doubled after you added a join. How do you find and fix the cause?
How do you identify and resolve performance bottlenecks in slow-running SQL queries?
Medium · Databases, SQL & Data Persistence
Approach
- Find the actual offender first: the MySQL slow query log, pg_stat_statements in PostgreSQL, or Query Store and DMVs in SQL Server. Reproduce it with real parameter values and real data volume.
- Read the plan with EXPLAIN / EXPLAIN ANALYZE or the actual execution plan. Look for full scans of large tables, a big gap between estimated and actual rows (stale statistics), key lookups repeated per row, sorts spilling to disk, and nested loops over large inputs.
- Index for the predicate: match WHERE, JOIN and ORDER BY columns, order composite keys by the leftmost-prefix rule (equality columns before range columns), and cover hot queries with INCLUDE columns.
- Make predicates sargable. YEAR(created_at) = 2024 becomes a date range, LIKE '%term' cannot seek, and implicit type conversions disable the index. Select only the columns you need, and replace deep OFFSET paging with keyset pagination.
- Check for causes outside the plan: lock blocking, N+1 queries from the ORM, missing statistics updates. Compare the plan and timings before and after the fix, and count the write cost of every new index.
Follow-up
- Why would the optimizer ignore an index that exists on the filtered column?
- A query is fast in development and slow in production. What differs, and what do you check?
- How do you choose the column order of a composite index?
What is an index in a database, and what are the tradeoffs between clustered and non-clustered indexes?
Medium · Databases, SQL & Data Persistence
Approach
- An index is a separate sorted structure, usually a B+ tree, that maps key values to row locations. A lookup becomes an O(log n) seek plus a range scan instead of a full scan. It costs storage, and every INSERT, UPDATE and DELETE must maintain it.
- A clustered index is the table itself: its leaf level holds the data rows in key order, so there is only one per table. SQL Server makes the primary key clustered by default, InnoDB always clusters on the primary key, and PostgreSQL tables are heaps (CLUSTER only reorders once).
- A non-clustered index holds the key plus a pointer: a RID for a heap, or the clustered key in SQL Server and InnoDB secondary indexes. A table can have many. Reading columns that are not in the index needs an extra lookup, unless the index covers the query (INCLUDE columns).
- Clustered key choice: narrow, unique and ever-increasing (an identity column). It suits range scans, and every secondary index carries a copy of it. A random GUID key causes page splits and fragmentation.
- Non-clustered trade-off: each extra index speeds some reads and slows every write. Low-selectivity columns such as a boolean flag rarely help on their own.
Follow-up
- What is a covering index, and how does it remove the key lookup?
- Why is a random GUID a poor clustered key?
- When would the optimizer choose a full scan even though an index exists?
What is a RESTful API, and what are the standard HTTP methods and status codes used in enterprise services?
Medium · Frameworks, Microservices & Web Developm
Approach
- REST models resources as URIs (plural nouns such as /orders/{id}/items, not verbs) and changes them through representations, usually JSON, using standard HTTP methods. It is stateless: every request carries its own authentication, such as a bearer token.
- Methods: GET reads and is safe and idempotent. POST creates or triggers an action and is not idempotent. PUT replaces the whole resource and is idempotent. PATCH is a partial update and is not guaranteed idempotent. DELETE is idempotent.
- Success codes: 200 OK, 201 Created with a Location header, 204 No Content. Client errors: 400 for validation, 401 when not authenticated, 403 when authenticated but not allowed, 404, 409 for a conflict or version clash, 422 for a semantically invalid body, 429 when rate-limited.
- Server errors: 500 for unexpected failures, 502/503/504 for upstream failure, unavailability and gateway timeout. Return one error body shape everywhere, for example RFC 7807 problem details, so clients can branch on it.
- Production concerns: versioning (/v1 in the path or a header), cursor or limit pagination, an idempotency key on POST so a retry after a timeout cannot create two orders, and OAuth 2.0 / JWT validation over HTTPS.
Follow-up
- Which of PUT, PATCH and POST are idempotent, and why does that matter when a client retries?
- What is the difference between 401 and 403? Give an example of each.
- How would you add a breaking field change without breaking existing clients?
Explain the architecture of a Spring Boot application or.NET Core Web API. How do dependency injection and ann
Medium · Frameworks, Microservices & Web Developm
Explain the architecture of a Spring Boot application or.NET Core Web API. How do dependency injection and annotations work?
Approach
- Describe the layers: a controller (@RestController, or [ApiController] on ControllerBase) handles HTTP and DTOs. A service layer holds business logic and transactions. A repository (Spring Data JPA, or EF Core's DbContext) talks to the database. Errors are handled in one place (@ControllerAdvice, or .NET exception middleware or filters).
- Spring Boot startup: @SpringBootApplication combines @Configuration, @EnableAutoConfiguration and @ComponentScan. Auto-configuration creates beans from what is on the classpath and in application.yml, and starts an embedded server such as Tomcat.
- Spring DI: the ApplicationContext creates beans and injects their dependencies. Prefer constructor injection (final fields, easy to test). The default scope is singleton, with prototype and request as alternatives. @Primary or @Qualifier resolve two beans of the same type.
- In .NET, Program.cs registers services with AddSingleton, AddScoped or AddTransient, and the middleware order matters (UseAuthentication before UseAuthorization). DbContext is scoped. Injecting a scoped service into a singleton is a captive-dependency bug, and scope validation throws on it in Development.
- Annotations are metadata read through reflection. Spring applies @Transactional through a proxy, so a call from one method to another in the same class bypasses the proxy and runs without the transaction.
Follow-up
- What happens at startup when two beans implement the same interface, and how do you pick one?
- Why does @Transactional on a method called from inside the same class not open a transaction?
- What goes wrong when a singleton service depends on a scoped DbContext?
How do microservices communicate synchronously and asynchronously? Contrast REST APIs with event-driven messag
Medium · Frameworks, Microservices & Web Developm
How do microservices communicate synchronously and asynchronously? Contrast REST APIs with event-driven messaging using Kafka or MQ.
Approach
- Synchronous calls (REST over HTTP, or gRPC) block the caller until the response arrives. They are simple and give an immediate answer, but they couple services in time: if the downstream service is down or slow, the caller fails too, and latency adds up along a chain.
- Make sync calls safe with timeouts on every call, retries with exponential backoff and jitter for idempotent operations only, and a circuit breaker (Resilience4j, Polly) that fails fast while a dependency is unhealthy.
- Asynchronous calls publish events or commands to a broker. The producer does not wait, spikes get buffered, and several consumers can react to one event. The price is eventual consistency.
- Kafka is a partitioned, replicated log. It keeps messages for a retention period whether or not they have been read, consumer groups track their own offsets, ordering holds only within a partition (so key by orderId), and you can replay. Classic queues (RabbitMQ, IBM MQ) remove a message once it is acknowledged and focus on routing.
- Delivery is usually at-least-once, so consumers must be idempotent (deduplicate on an event id), with a dead-letter queue for poison messages. Use the outbox pattern to avoid a dual write between the database and the broker, and a Saga with compensating steps for a transaction that spans services.
Follow-up
- How do you guarantee that a database update and its event are both published, or neither is?
- How do you keep one customer's events in order in Kafka while still scaling consumers?
- A consumer processes a message, then crashes before committing its offset. What happens, and how do you make that safe?
Describe strategies for optimizing page load performance in a modern single-page application (SPA).
Medium · Frameworks, Microservices & Web Developm
Approach
- Measure before changing anything. Run Lighthouse and the DevTools Performance panel, read the Core Web Vitals (LCP, INP, CLS), and use a bundle analyzer (webpack-bundle-analyzer or source-map-explorer) to see what ships.
- Ship less JavaScript: split code by route with dynamic import() plus React.lazy and Suspense, rely on tree shaking, replace heavy libraries, and serve minified assets compressed with gzip or Brotli.
- Delivery: put content-hashed assets on a CDN with long-lived cache headers and serve index.html with no-cache so deploys take effect. Preload critical fonts and CSS and defer non-critical scripts.
- First paint: server rendering or static generation (for example Next.js) sends HTML before the JS runs. For images, use responsive srcset, WebP or AVIF, loading="lazy" below the fold, and explicit width and height to prevent layout shift.
- Data and rendering: fire independent API calls in parallel instead of as a waterfall, cache responses (React Query, SWR), virtualise long lists (react-window), and memoise expensive components only after profiling shows wasted renders.
Follow-up
- How do you tell whether a slow load comes from the network, JavaScript parse and execute time, or a slow API?
- What do you gain and lose with server-side rendering compared with client-only rendering?
- After a deploy, users get stale JavaScript. How do you prevent it?
What is the Collection Framework in Java, and how does a HashMap work under the hood?
Medium · Databases, SQL & Data Persistence
Approach
- Map the framework: Collection splits into List (ArrayList, LinkedList), Set (HashSet, LinkedHashSet, TreeSet) and Queue/Deque (ArrayDeque, PriorityQueue). Map is a separate hierarchy (HashMap, LinkedHashMap, TreeMap). Pick by access pattern: ArrayList gives O(1) indexed reads, TreeMap gives sorted keys at O(log n).
- HashMap stores entries in an array of buckets. It spreads the key's hashCode() as h ^ (h >>> 16) and picks the bucket with (n - 1) & hash, where n is a power of two. Colliding entries chain in a linked list.
- Since Java 8, a bucket whose chain grows past 8 entries turns into a red-black tree if the table has at least 64 buckets; below that, the map resizes instead. The defaults are capacity 16 and load factor 0.75, so the table doubles once size exceeds 12, and entries are split into low and high lists.
- Complexity: get and put are O(1) on average. A single overloaded bucket costs O(n) as a list, or O(log n) once treeified. One null key is allowed (it hashes to bucket 0), iteration order is not guaranteed, and HashMap is not thread-safe, so use ConcurrentHashMap.
- The equals/hashCode contract: equal keys must return equal hash codes. A mutable key whose hashCode changes after insertion becomes unreachable.
Follow-up
- What happens if a key class overrides equals but not hashCode?
- How do HashMap, Hashtable and ConcurrentHashMap differ under concurrent writes?
- Build an LRU cache with LinkedHashMap. Which constructor flag and which method override do you need?
How does Hibernate or Entity Framework manage entity states, lazy loading, and database transactions?
Medium · Databases, SQL & Data Persistence
Approach
- JPA/Hibernate entity states: transient (new, untracked), managed (in the persistence context, changes tracked), detached (the context closed; merge() reattaches it) and removed (deleted at flush). EF Core's ChangeTracker uses Added, Unchanged, Modified, Deleted and Detached.
- Dirty checking: at flush or commit, Hibernate compares managed entities against their loaded snapshot and issues UPDATEs, so a managed entity needs no explicit save call. EF Core writes tracked changes when SaveChanges() runs.
- Lazy loading: associations load through proxies on first access. JPA defaults are LAZY for @OneToMany and @ManyToMany and EAGER for @ManyToOne and @OneToOne. Touching a lazy field after the session closes throws LazyInitializationException. In EF Core, lazy loading is opt-in (UseLazyLoadingProxies plus virtual navigation properties); otherwise use Include() or explicit loading.
- N+1: loading 100 orders and then touching each order's customer fires 101 queries. Fix it with JOIN FETCH, @EntityGraph or batch fetching in Hibernate, or Include() in EF Core, and catch it by turning on SQL logging.
- Transactions: Spring's @Transactional defaults to REQUIRED propagation and rolls back on unchecked exceptions only (checked ones need rollbackFor). EF Core wraps each SaveChanges in a transaction, and Database.BeginTransaction() spans several calls. For optimistic locking, use @Version or a rowversion/[ConcurrencyCheck] column.
Follow-up
- How do you fix a LazyInitializationException without making every association EAGER?
- How would you detect an N+1 problem in a running service, and how would you fix it?
- Two users update the same row with optimistic locking on a version column. What happens to the second one?
Read latency spikes on a sixty-second sawtooth
Medium · cache stampede · single-flight · ttl
The cached listing read path serves about 14k reads/second at an 85% hit rate. p99 sits at 35 ms for 57 seconds, jumps to 900 ms for 3, and repeats. During each spike the primary shows several hundred identical listing queries starting within the same millisecond, all carrying one large tenant's id. Cache entries use a 60-second TTL. Give the mechanism, the ordered checks, the fix, and the correctness hazard your fix must not introduce.
Approach
- Match the period to a configured number before theorising about load. A spike every 60 seconds against a 60-second TTL is an entry expiring, and you confirm it by correlating spike timestamps with the entry's write time rather than with the traffic curve. If the period had matched a cron or a GC interval instead, this is a different investigation.
- Establish the concurrency of the miss. Several hundred identical queries in one millisecond means the miss path has no coalescing: every request that arrives between expiry and repopulation recomputes. The herd size is that key's arrival rate times its recompute time, so at 1.2k reads/second for the hot key and a 250 ms recompute you expect about 300 concurrent misses, which matches what is observed.
- Add single-flight on the miss path so one caller per key recomputes under a short-lived lock while the rest wait for its result. Prefer stale-while-revalidate where the read tolerates it: return the expired value immediately and refresh asynchronously, which removes the latency spike rather than serialising it into a queue of waiters.
- De-synchronise the keys. Write TTLs with jitter, for example 60 seconds plus or minus 10%, so a deploy or a mass invalidation does not align every key on the same second and turn a per-key herd into a fleet-wide one.
Follow-up
- The same sawtooth appears on a key that is invalidated on write rather than expired. Is that the same bug?
- How does your answer change if the recompute takes 4 seconds instead of 250 ms?
Suggested practice checklist
The plan moves through the reported rounds: resume and stack first, then OOP, live coding, databases, frameworks, behavioral stories and a full mock loop. Each day points at the reported questions it practises.
Day 1 — Resume audit and your primary stack
- List every technology and project on your resume, and write your role, one design decision and one trade-off for each.
- Choose the primary stack (Java, .NET, Python or full-stack JavaScript) you will answer in, and note the equivalents on the other side, such as Hibernate and Entity Framework.
- Write and speak your two-minute resume walk-through and your answer on why you are leaving and what you want next.
Deliverable: A resume audit sheet with project notes per technology, a spoken two-minute pitch, and a written answer on leaving your previous organisation and your goals.
Day 2 — OOP, SOLID and core language mechanics
- Write one small order-service example in your language that shows abstraction, encapsulation, inheritance and polymorphism.
- Write a demo of overloading versus overriding, and say which is resolved at compile time and which at runtime.
- Refactor a class with a hard-coded dependency to constructor injection and test it with a fake, then explain dependency inversion.
- Write down what static members share, where objects and references live (stack and heap), and when garbage collection frees them.
Deliverable: One runnable file or repository with the four-pillar example, overload/override demo and injected-dependency test, plus spoken answers for the interface versus abstract class decision.
Day 3 — Live coding on strings and matrices
- In a plain editor with no autocomplete, write string reversal without library helpers, palindrome checks for strings and numbers, and character-frequency and repeated-character solutions with a map and, if your language has them, streams.
- Write matrix rotation by 90 degrees, diagonal sum, and a path-finding traversal on a grid.
- For each solution, list edge cases, test them, and write the time and space complexity.
Deliverable: A set of solved problems, each with edge-case tests and a one-line complexity note.
Day 4 — SQL, indexes and persistence
- Write queries over three related tables using inner, left, right and full joins, and one that inflates a sum through a one-to-many join, then fix it.
- Write the second-highest-salary query three ways (subquery with MAX, LIMIT/OFFSET, DENSE_RANK) and compare how each handles ties.
- Take a slow query, read its execution plan, add an index and explain clustered versus non-clustered storage.
- Write a Pandas null-cleaning routine with the matching SQL COALESCE version, then explain how HashMap and Hibernate or Entity Framework manage entities.
Deliverable: A SQL file with annotated queries and plans, a null-cleaning script, and spoken answers on indexes, HashMap internals and ORM entity states.
Day 5 — Frameworks, REST and microservice messaging
- Design a small REST resource with methods, status codes and error shapes, and say how you would secure it with OAuth 2.0 and JWT.
- Draw the request flow of a Spring Boot or .NET Core Web API and explain how dependency injection and annotations or attributes wire it.
- Compare REST calls with Kafka or MQ messaging for one order flow, and sketch a high-throughput financial-transaction service with retries and idempotency.
- Write a decision table for React or Vue state (local, server cache, URL, global store) and a list of SPA load-time fixes.
Deliverable: One page of diagrams and tables covering REST, framework flow, sync versus async messaging, frontend state and SPA performance, each rehearsed aloud.
Day 6 — Behavioral stories and client readiness
- Write STAR outlines with a number in the result for a hard bug, a mid-sprint change in priorities, a technical disagreement and onboarding onto an unfamiliar codebase.
- Explain one project decision to a non-engineer in under a minute of speech and record yourself.
Deliverable: Four STAR outlines, a practised latency diagnosis, and one recorded explanation for a non-technical listener.
Day 7 — Full-loop mock
- Answer a rapid-fire set aloud: OOP, SOLID, REST, indexes, HashMap, with one example each.
- In a plain editor, solve one string problem, one matrix problem and one SQL query, explaining as you go.
- Test camera, microphone and connection for any recorded or proctored stage, and write the questions you will ask the recruiter and the client.
Deliverable: A mock session log listing answers that were weak, the coding and SQL solutions from the session, and a final question list for the recruiter and client.
Project stories and client readiness
Candidates report that the scenario and managerial questions cover technical hurdles, working in Agile client teams and recovering from project setbacks. Because engineers are placed with clients, expect your stories to be tested for personal contribution, communication and how you handle shifting requirements. Use STAR, say 'I' for your own actions, and give a measurable result. Two reported questions in this group, null handling in Pandas and React or Vue state, need technical answers instead of stories.
- Walk me through one project on your resume: your exact role, the database and deployment choices, and one trade-off you made.
How do you handle and clean null values in a dataset using Python (Pandas and NumPy)?
Medium · Practical Coding, Algorithms & Data Stru
Approach
- Profile before fixing: df.info(), df.isna().sum() and df.isna().mean() show which columns are affected and how badly. Look for hidden nulls such as empty strings, 'N/A', -1 or 0 used as a sentinel, and convert them with na_values in read_csv or df.replace(..., np.nan) so they are counted.
- Decide per column and say why. Use dropna(subset=[key columns]) when a row is useless without that field or few rows are hit. Impute when dropping would bias the data: median for skewed numerics, mode or an explicit 'Unknown' category for labels, ffill or interpolate only on data sorted by time, and groupby(...).transform('median') when the group explains the value.
- Keep the fact that a value was missing: add an is_missing flag column before imputing when absence may carry signal, and log how many rows each rule changed. If the data feeds a model, compute fill statistics on training rows only so test rows do not leak in.
- Know the library traps. NaN != NaN, so test with isna(), not ==. An integer column with nulls becomes float unless you use nullable Int64. Pandas sums and means skip NaN by default while np.mean returns nan (use np.nanmean). groupby drops NaN keys unless dropna=False. Prefer df['c'] = df['c'].fillna(x) over chained assignment or inplace.
- Close with the SQL side of the same problem: COUNT(col) skips nulls while COUNT(*) does not, AVG ignores nulls, a comparison with NULL is unknown, and COALESCE supplies a default. Say whether a missing value should count as zero or be excluded before you aggregate.
Follow-up
- When does filling with the mean distort the result, and what would you use instead?
- The file is too large to load into memory. How do you clean it?
- How do you confirm that cleaning did not shift the distribution or wipe out an entire segment?
In React or Vue.js, how do you handle state management across complex application component trees?
Medium · Frameworks, Microservices & Web Developm
Approach
- Sort state by what it is before choosing a tool. Local UI state stays in the component (useState in React, ref in Vue). Server data belongs in a fetch cache with invalidation (React Query or SWR in React). URL state such as filters and page belongs in the router. Only state that many distant components truly share needs a global store.
- Lift state to the nearest common ancestor first. When props pass through many layers, use Context in React or provide/inject in Vue for values that change rarely, such as theme, locale or the signed-in user. Context re-renders every consumer when its value changes, so it is a poor home for fast-changing data.
- For shared state with frequent updates, use a store with selectors so each component subscribes to only its slice: Redux Toolkit or Zustand in React, Pinia in Vue. Use a reducer (useReducer or Redux actions) when transitions are complex, so every change is a named event you can log and test.
- Store the minimum and derive the rest (useMemo in React, computed in Vue). Keep entities normalised by id so one update does not need edits in several places. Name the trade-off: Redux-style stores cost boilerplate but give traceability and devtools, while lighter stores are quicker to write and easier to misuse.
- Cover async edge cases: responses that arrive out of order (cancel or ignore stale requests), optimistic updates with rollback on failure, and stale closures inside effects.
Follow-up
- A theme toggle and a fast-updating shopping cart are both global. Would they use the same mechanism?
- Typing in one input re-renders the whole page. How do you find the cause and fix it?
- Where does fetched data live, and how does it refresh after a mutation?
Describe a challenging bug or performance issue you encountered in a recent project and how you diagnosed and
Medium · Scenario-Based & Behavioral Questions
Describe a challenging bug or performance issue you encountered in a recent project and how you diagnosed and resolved it.
Approach
- Choose a bug you personally owned whose symptom you can state in numbers: an endpoint that rose from one latency to another, a batch job that missed its window, a memory climb that ended in restarts. Give the situation in two sentences, because the value of the story is in the diagnosis.
- Narrate the diagnosis in order: how you reproduced or bounded the problem with logs, metrics or traces; what you ruled out; which tool localised it (profiler, thread or heap dump, SQL execution plan, network trace); and the hypothesis you tested by changing one thing at a time.
- State the root cause as a mechanism, not a symptom: an N+1 query from lazy loading, a missing index forcing a full scan, an unbounded cache, a lock held across a remote call, a consumer acknowledging a message before processing it. Use the one you really hit.
- Report the result as before and after figures, then say what stops it recurring: a regression test, an alert, a review checklist item or a runbook note. Add what you would do earlier next time.
- Avoid three stories that sink this answer: a fix that was a restart or retry with no cause found, a solution a colleague found, and a result with no measurement.
Follow-up
- How did you confirm that was the root cause rather than a change that happened at the same time?
- What would you have done if you could not reproduce it outside production?
- What did you change so the same class of problem is caught earlier?
How do you handle conflicting priorities or changing requirements mid-sprint?
Medium · Scenario-Based & Behavioral Questions
Approach
- Open with the commitment, then the change: what the sprint had promised, what arrived, who asked, and whether it truly could not wait. Show that you first asked what problem the new request solves and by when it is needed.
- Size the change quickly and make the trade-off visible: say what moves out of the sprint if the new item moves in. Take that choice to the product owner or whoever owns priority. Your part is the estimate and the risks, not quietly absorbing extra work or silently dropping something.
- If the change comes from a client stakeholder, describe how you confirmed the requirement in writing, informed the team, updated the sprint plan or backlog, and kept testing in scope instead of trading it away.
- Give the outcome with specifics: what shipped, what was deferred and who agreed. Close with a process fix, such as refinement before sprint start, a small buffer or a change-request step.
- The answers that sink this question are 'I worked extra hours' with no prioritisation, and a flat refusal with no alternative offered.
Follow-up
- Two stakeholders insist their item comes first and neither will give way. What do you do next?
- Requirements change several times in one sprint. What would you change in how the team works?
- How did you tell the person whose item was deferred?
Tell me about a time you had a technical disagreement with a team member or tech lead. How did you resolve it?
Medium · Scenario-Based & Behavioral Questions
Approach
- Pick a disagreement with real technical content: synchronous REST versus messaging between services, an ORM versus hand-written SQL, an abstract class versus an interface, adding a cache, or a rewrite versus incremental refactoring. Describe both positions fairly, including the strongest argument on the other side.
- Name the criteria you could both accept (latency target, failure behaviour, maintenance cost, deadline) and the evidence that moved the discussion: a spike, a benchmark, a prototype or a short written comparison.
- Say who owned the decision. If it went against you, show that you raised the concern once with data, then committed and helped it succeed. If it went your way, show what you conceded and how you kept the other person's concern on the list.
- Give the outcome and the working relationship afterwards: what shipped, what was measured and how you collaborated from then on.
- Avoid a story where you were simply right and the other person wrong, one where you stayed silent, and any hint of blame.
Follow-up
- What if the benchmark had shown you were wrong?
- The tech lead overruled you and you still believed it was a mistake. What did you do?
- Would you handle it differently today?
Why did you leave your previous organization, and how do your technical career goals align with Ascendion?
Medium · Scenario-Based & Behavioral Questions
Approach
- Answer in three beats: the factual reason you are moving, framed as a pull toward something rather than a complaint; what you built and learned in your last role; and what you want next. Keep the first beat to a sentence or two and make sure it matches your resume dates and what you told the recruiter.
- Do not criticise the previous employer, manager or team. Name constraints neutrally, such as a single stack, a narrow product or little client exposure, and move on to what you want.
- Tie your goals to what candidates describe about this role: engineers placed on client engagements, work across several client domains, a mix of backend, frontend and database work, and different stacks between projects. Pick the parts that are true for you and give one piece of evidence that you adapt quickly, such as learning a new framework to deliver a project.
- Keep the goals concrete: a stack to go deeper in, a type of problem, or the skill of working directly with client teams. A sentence that would fit any consulting firm adds nothing.
- Be ready to say plainly how you feel about moving between client projects and technologies, since that is part of how the role is described.
Follow-up
- How would you feel about switching stack or domain when a client project ends?
- What would make you leave this role as well?
- Which part of your current work do you most want to keep doing here?
What steps do you take when onboarding onto an unfamiliar codebase or legacy client application?
Medium · Scenario-Based & Behavioral Questions
Approach
- Start by getting it running: clone, build, run the tests, start the app locally with seed data. Note every missing step and fix the README as you go. A build you cannot reproduce is a blocker to name early.
- Read from the outside in: the README, any architecture diagram, deployment configuration, then trace one real use case end to end (entry point, controller or handler, service, data access, database) and write the trace down. Map external dependencies such as queues, other services and scheduled jobs.
- Treat history and tests as documentation: git log and blame on the most-changed files, the issue tracker for recurring defects, and existing tests for intended behaviour. If tests are absent, write characterisation tests that pin current behaviour before editing.
- Learn from people with a short, prepared question list: who owns each area, what is fragile, what failed in production lately. Make a small first change or bug fix to exercise the review and deployment path.
- In legacy and client settings, do not rewrite what you do not yet understand. Change in small, reversible steps behind tests, record decisions, and confirm access, environments and change windows with the client contact.
Follow-up
- There is no documentation and the original authors have left. What do you do first?
- How do you decide what to refactor and what to leave alone?
- How do you avoid breaking a client's production while you are still learning the system?