cswork / libraryOpen practice workspace

Interview guides · Coherent Solutions

Coherent Solutions Software Engineer Interview Guide

Coherent Solutions Software Engineer interview guide: 3 reported rounds, Java and Spring topics, coding and behavioral prep, plus a 7-day plan.

The 60-second brief

Candidate material describes Coherent Solutions as a company where software engineers build technology solutions for clients and their end users, working alongside product managers, designers and other engineers. The stack candidates list for the role is Java, C# or Python, with Spring or .NET on the framework side, plus HTML, CSS and JavaScript for web work, SQL and NoSQL databases, Git, CI/CD pipelines and agile practice. AWS or Azure, microservices, RESTful API design, Docker and Kubernetes are named as extras. The reported topic breakdown for this loop centres on Java, the Spring Framework, Spring Boot and Spring's dependency injection container, alongside general problem-solving.

This guide is for engineers preparing for the Software Engineer loop at Coherent Solutions. It covers the three reported rounds (Preliminary Screening, Coding Interview, Behavioral Interview), the twenty technical, coding, architecture and behavioral questions candidates report, the Java and Spring material that shows up in the topic breakdown, and a seven-day schedule. It does not cover other roles at the company.

Candidates report three rounds over roughly three to five weeks: a Preliminary Screening, a Coding Interview and a Behavioral Interview. The reported questions fall into technical and domain, coding and algorithms, behavioral, and system design groups.

Focus areas

  • Spring Framework
  • Java
  • Problem-Solving / Reasoning

Overview

The reported question set is broad rather than deep in any single area. It runs from object-oriented principles, synchronous versus asynchronous programming, error handling, SQL versus NoSQL and REST design, through classic coding exercises (reverse a linked list, binary search, merging sorted arrays), to architecture questions on microservices versus a monolith, database design under heavy traffic, security, load balancing and performance tuning, and finally a set of standard behavioral prompts. Preparing for it means being able to give a short, correct, example-backed answer on each of these, not mastering one niche.

The topic breakdown candidates describe is dominated by Java and the Spring family: the Spring Framework, Spring Boot, and the container concepts behind dependency injection. Even when a question is phrased generically, such as the one on object-oriented principles or on error management, a Java and Spring answer is the natural way to make it concrete. Be ready to explain what a bean is, how constructor injection differs from field injection, what Spring Boot auto-configuration saves you from writing, and how a controller advice handles exceptions. If your strongest language is C# or Python, which the requirements also list, prepare the equivalent in .NET or your framework and say so early.

The role as candidates describe it mixes designing and building applications, working with product managers and designers, taking part in code reviews, and troubleshooting existing applications. That is why the loop pairs a coding round with a behavioral one focused on team dynamics. Your examples should show code you wrote and changed, reviews you gave and received, and a bug you tracked down in something already running.

A practical way to spend your time: put the first days into Java and Spring fundamentals and the coding drills, because they are the most concrete and the easiest to rehearse aloud; spend the middle of the week on databases, APIs, performance and architecture trade-offs; and keep the last two days for behavioral stories and a full spoken run-through.

The Coherent Solutions interview process

Candidates describe three stages, listed below in the order they report them. The material says little about format inside each stage, so the preparation advice here is tied to the question types each stage covers.

Preliminary Screening

Candidates describe the Preliminary Screening as an initial discussion of your technical skills and experience. Little more is reported about its format, so treat it as a conversation where your résumé and the requirements for the role meet: Java, C# or Python, web technologies, SQL and NoSQL, and the practices around them. Go in with a short walkthrough of your most relevant project and clear one-minute answers to the foundational technical questions reported for this company, such as the principles of object-oriented programming, synchronous versus asynchronous programming, SQL versus NoSQL, and how you handle errors.

What to demonstrate

  • How clearly you describe your own technical experience and the decisions in it
  • Whether your background lines up with the requirements candidates describe for the role
  • Command of foundational concepts when they are asked about in conversation rather than in code

How to prepare

  • Build a one-page stack inventory: for each requirement (Java or C# or Python, a Spring or .NET framework, SQL, NoSQL, Git, CI/CD) write one project where you used it and what you personally did
  • Rehearse a two-minute project walkthrough that states the problem, your component, one hard decision and the outcome
  • Give spoken answers to the object-oriented principles and synchronous versus asynchronous questions with a Java example each, so the answers are concrete rather than textbook

Coding Interview

Candidates describe the Coding Interview as programming challenges solved live while explaining your thinking. The reported coding questions are a data-structures problem at LeetCode medium level, reversing a linked list, implementing binary search, optimizing a function for performance, and narrating your thought process as you code. Example scenarios mentioned include merging two sorted arrays and optimizing a search over large datasets. Choose one language you can write without an IDE (Java is the safest given the topic breakdown), state the brute-force approach and its complexity first, then improve it, and say the complexity of the final version aloud.

What to demonstrate

  • Working code written live in a language you choose to be fluent in
  • Choice of data structure and algorithm, with time and space complexity stated
  • Ability to explain your reasoning while writing
  • Handling of edge cases: empty input, single element, duplicates, off-by-one boundaries

How to prepare

  • Write reverse a linked list iteratively and recursively from memory, then explain the pointer moves for a three-node list
  • Write binary search in both the inclusive and half-open styles, and a variant that returns the first matching index when duplicates exist
  • Implement merging two sorted arrays with two pointers, and state why it is linear and where an in-place version needs a back-to-front pass
  • Practise narrating: say the approach before typing, name the invariant, and test with one normal and one edge input out loud

Behavioral Interview

Candidates describe the Behavioral Interview as focused on cultural fit and team dynamics. The reported prompts cover a challenging project, prioritizing across several projects, a conflict within a team, what motivates you, and how you approach feedback; related material also mentions collaboration with cross-functional teams and handling change or ambiguity. Prepare a small set of real stories that each answer several of these prompts, with your own decisions in the foreground and an outcome you can state.

What to demonstrate

  • Examples of working inside a team and what your own contribution was
  • How you handled conflict, competing priorities, change or ambiguity, as candidates describe the stage
  • Motivation and approach to feedback, shown through specific events

How to prepare

  • Write three stories (a hard project, a disagreement, a feedback moment), each in situation, action, result form, with one number or observable outcome
  • Check that each story names a decision you made, not only what the team did
  • Practise the prioritization and motivation questions aloud, since they have no single story and tend to ramble
  • Prepare two questions about how engineers, product managers and designers work together on a project

Where candidates lose points

Writing linked-list or binary-search code from memory without testing it on an edge case

After writing, run a three-node list and an empty list through reverse, and run a one-element array and a missing target through binary search. Check the loop bound (low <= high versus low < high) and the midpoint formula low + (high - low) / 2.

Answering the object-oriented principles question as a memorised list of four words

For encapsulation, inheritance, polymorphism and abstraction, give one Java example each, and say when composition beats inheritance. A short example is more useful than a definition.

Giving the same microservices-are-better answer to the monolith versus microservices question

Present both sides: a monolith is simpler to deploy, test and debug; services allow independent scaling and deployment but add network failure, distributed data and operational overhead. Say which fits a small team and which fits many teams.

Knowing Java but not the Spring pieces the topic breakdown emphasises

Be able to explain beans, the container, constructor versus field injection, what Spring Boot auto-configuration does, and how @ControllerAdvice or @Transactional behave. Practise saying it in your own words.

Telling behavioral stories in which the team did everything and your own decision is invisible

For each story, write the sentence beginning "I decided" before rehearsing. Add the outcome with a number or an observable change, and one thing you would do differently.

Questions & practice

Can you explain the difference between synchronous and asynchronous programming?

Medium · Technical / Domain Questions

Approach

  1. Define both precisely. A synchronous call blocks the caller until the result is ready. An asynchronous call starts the work and returns at once, and the result arrives later through a callback, future, promise or await.
  2. Do not treat async as the same thing as multithreading. JavaScript runs async I/O on a single-threaded event loop, and Python asyncio switches between tasks cooperatively on one thread. Java's CompletableFuture *Async methods run on a thread pool (the common ForkJoinPool unless you pass an executor), and C# async/await works with Task.
  3. Say where async pays off. For I/O-bound work such as HTTP or database calls, it frees threads while they wait. It does not speed up CPU-bound work, and a single blocking call inside an event loop stalls every other task on it.
  4. Give the latency argument with an example: three independent service calls made one after another take roughly the sum of their latencies; started together and awaited together, they take roughly the slowest one.
  5. Cover error handling and the costs. Exceptions travel through the future and are re-thrown at await or handled with exceptionally/handle. An unhandled rejection can fail silently. Stack traces are harder to read, ordering is no longer guaranteed, and you need timeouts and backpressure.

Follow-up

  • What happens if you make a blocking JDBC call inside an event-loop or reactive handler?
  • How would you run three independent calls concurrently, fail if any of them fails, and apply an overall timeout (CompletableFuture.allOf, Promise.all, asyncio.gather)?
  • What is the difference between concurrency and parallelism?

Solve a LeetCode medium-level problem related to data structures.

Medium · Coding / Algorithms

Approach

  1. Before choosing anything, confirm the input size, whether the input is sorted, whether duplicates or negatives occur, and what to return when nothing matches. Then state the brute-force solution and its complexity so there is a correct baseline.
  2. Pick the structure from the operation that has to be fast: a hash map or set for O(1) average lookups (two-sum, grouping anagrams), a stack for matching or monotonic problems (valid parentheses, next greater element), a heap for top-k in O(n log k), a deque or queue for BFS and sliding-window maximum, and two pointers on sorted input.
  3. Know the combined-structure classic. An LRU cache uses a hash map plus a doubly linked list so that get and put are both O(1). In Java, LinkedHashMap with accessOrder=true and an overridden removeEldestEntry gives the same behaviour.
  4. Code it in your interview language, trace one small example by hand, then test the edge cases: empty input, one element, all duplicates, negatives, and integer overflow on sums.
  5. Close with the time and space complexity and the trade-off you made, such as spending O(n) memory on a hash map to bring the time down from O(n^2) to O(n).

Follow-up

  • Implement the LRU cache without LinkedHashMap.
  • For top-k frequent elements, compare the heap solution with bucket sort, which runs in O(n).
  • How does your solution change if the input arrives as a stream you cannot store?

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Write the iterative version with three references. Set prev = null and curr = head. In each step: save next = curr.next, set curr.next = prev, then move prev = curr and curr = next. When curr is null, return prev as the new head. This runs in O(n) time and O(1) extra space.
  2. Explain the one ordering rule that matters: save curr.next before you rewire it, or the rest of the list is lost.
  3. Give the recursive version as an alternative. Reverse the rest of the list from head.next, then set head.next.next = head and head.next = null, and return the new head that the recursion produced. It is O(n) time but also O(n) call stack, so a very long list can throw StackOverflowError in Java.
  4. Test the empty list, a single node and two nodes, and confirm that the old head now points to null so the result has no cycle. For a doubly linked list, swap prev and next on every node and return the last node.

Follow-up

  • Reverse only the nodes between positions left and right in a single pass.
  • Reverse the list in groups of k nodes, leaving a final group shorter than k unchanged.
  • Check whether a linked list is a palindrome using O(1) extra space (find the middle with slow and fast pointers, reverse the second half, compare, then restore it).

Can you implement a binary search algorithm?

Medium · Coding / Algorithms

Approach

  1. State the precondition first: the array must be sorted, or more generally there must be a predicate that is monotonic over the search range. Then write the iterative version: lo = 0, hi = n - 1, loop while lo <= hi, and compare a[mid] with the target to move lo = mid + 1 or hi = mid - 1. Return -1 if the target is not found.
  2. Compute mid = lo + (hi - lo) / 2 rather than (lo + hi) / 2. In Java and C#, lo + hi can overflow int on large arrays. This exact bug was once present in the JDK's own binary search.
  3. State the invariant: if the target is present, it lies in [lo, hi], and the range shrinks on every iteration. The search takes O(log n) time and O(1) space when written iteratively.
  4. Know the boundary variants. For the lower bound (first index whose value is >= target), use the half-open range [lo, hi), loop while lo < hi, and set hi = mid when a[mid] >= target, otherwise lo = mid + 1. That variant handles first and last occurrence when there are duplicates. In Java, Arrays.binarySearch returns -(insertionPoint) - 1 when the key is missing; Python has bisect_left and bisect_right.
  5. Test the empty array, one element, a target smaller or larger than every element, and runs of duplicates. Mention binary search on the answer space, such as the minimum ship capacity that delivers all packages within D days.

Follow-up

  • Search for a target in a rotated sorted array.
  • Return the first and last position of a target in an array that contains duplicates.
  • Compute the integer square root of n without a library call.

How would you optimize a function for performance?

Medium · Coding / Algorithms

Approach

  1. Measure before changing anything. Reproduce the slow case with realistic input sizes, profile it (JFR, async-profiler or VisualVM for Java; cProfile for Python; dotnet-trace for .NET), and benchmark with JMH in Java so that JIT warm-up does not distort the numbers. Agree on a target number.
  2. Fix the algorithm first. Replacing a nested-loop membership check, O(n*m), with a HashSet lookup, O(n+m), or sorting once and using two pointers, beats any micro-tuning.
  3. Then remove constant-factor waste: work repeated inside loops that could be hoisted out, string concatenation in a loop (switch to StringBuilder to go from O(n^2) to O(n) copying), boxing in hot collections, and memoization for repeated pure calls.
  4. If the function does I/O, look at round trips before CPU. Batch database calls, fix N+1 queries, reuse pooled connections, and cache results that change rarely, with a clear invalidation rule.
  5. State the trade-offs and check the result. Speed often costs memory or readability, so keep tests green and report before-and-after numbers from the same benchmark.

Follow-up

  • How would you find the hot spot in a production service that you cannot attach a debugger to?
  • When does adding a cache make performance or correctness worse?
  • How would you fix an N+1 query in Spring Data JPA (JOIN FETCH, @EntityGraph, batch fetching)?

Explain your thought process while coding a solution.

Medium · Coding / Algorithms

Approach

  1. Restate the problem in your own words, walk one example from input to output, and ask about the constraints: input size, sortedness, duplicates, nulls and the expected return on failure.
  2. State the brute-force solution and its complexity out loud, name the step that makes it slow, and name the data structure or technique that removes that step before you write any code. For example: "I'll check every pair in O(n^2) first; the repeated lookup is the cost, so a hash map makes it O(n)."
  3. While coding, narrate the invariant each loop maintains, pull repeated logic into small helper functions, and say explicitly when you are deferring an edge case so it does not get forgotten.
  4. Test by tracing a small input line by line, then list the edge cases (empty, one element, duplicates, extreme values) and fix any bug aloud rather than silently.
  5. Finish with time and space complexity, and with what you would add for production code: input validation, unit tests and behaviour at larger scale.

Follow-up

  • You are stuck partway through. What do you say, and what do you try next?
  • Which unit tests would you write for the function you just coded?
  • How do you decide when a solution is good enough to stop optimizing?

What are the key differences between SQL and NoSQL databases?

Medium · Technical / Domain Questions

Approach

  1. Contrast the data models. Relational databases store normalized tables with a fixed schema, foreign keys and joins. NoSQL is a set of families rather than one design: document stores (MongoDB), key-value stores (Redis, DynamoDB), wide-column stores (Cassandra) and graph databases (Neo4j).
  2. Contrast the guarantees. Relational engines give ACID transactions across many rows and tables. Many NoSQL stores guarantee atomicity per item or document and offer eventual or tunable consistency, although some have added multi-document transactions (MongoDB since 4.0). Link this to CAP: when the network partitions, a system has to give up either consistency or availability.
  3. Contrast scaling and querying. Relational systems usually scale up and add read replicas; sharding them makes cross-shard joins expensive. Many NoSQL stores partition by key from the start, but they answer queries efficiently only along the keys and indexes you designed. That is why NoSQL modelling starts from the access patterns and denormalizes.
  4. Finish with a decision rule and examples: orders and payments, which need multi-row integrity and ad-hoc reporting, go relational; session data or a cache goes to a key-value store; high-volume append-only events can go to a wide-column store. Systems often use more than one store.

Follow-up

  • How would you model users and their orders in a document store, and when would you embed the orders rather than reference them?
  • When would you add a NoSQL store next to an existing relational database, and how would you keep the two in sync?
  • Where does a database you have used sit under CAP, and what did that mean for your application?

Keep soft-deleted accounts from blocking re-registration

Easy · soft delete · unique constraints · engine differences

app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.

Approach

  1. Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
  2. Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
  3. For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
  4. State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.

Follow-up

  • A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
  • How do you honour an erasure request while resource_revision.actor_user_id still references this table?

What are the main principles of object-oriented programming?

Medium · Technical / Domain Questions

Approach

  1. Name the four principles and attach a concrete example to each: encapsulation (private fields changed only through methods that guard an invariant, such as a balance that can never go negative), abstraction (callers depend on a PaymentGateway interface rather than on the class behind it), inheritance (a subclass reuses and extends a base type) and polymorphism (one call resolves to different implementations).
  2. Separate the two kinds of polymorphism. Overloading is resolved at compile time from the argument types. Overriding is resolved at runtime by dynamic dispatch. Java instance methods are virtual by default; in C# a method must be marked virtual and the subclass must use override.
  3. Keep abstraction and encapsulation apart: encapsulation hides state and protects invariants, while abstraction hides the implementation behind a contract. Mixing the two up is the most common weak answer.
  4. Bring in the trade-offs: prefer composition over deep inheritance (the fragile base class problem), and respect Liskov substitution. Square extending a mutable Rectangle is the classic violation, because setting the width also changes the height.
  5. Tie it to day-to-day Java or Spring work: when classes depend on interfaces, the container can inject any implementation through dependency injection, and tests can swap in a mock without touching the caller.

Follow-up

  • When would you choose an abstract class over an interface in Java, now that interfaces can have default methods?
  • Give an example of a subclass that breaks Liskov substitution, and say how you would redesign it.
  • Two Spring beans implement the same interface. How does the container decide which one to inject (@Primary, @Qualifier)?

How would you design a scalable microservices architecture for a web application?

Medium · System Design / Architecture

Approach

  1. Clarify scope first: the main features, expected users, read/write ratio and latency targets. Then split services along business capabilities, for example users, catalog, orders and payments. Each service owns its own database; a shared database couples the services back together.
  2. Lay out the request path: client, CDN for static assets, load balancer, then an API gateway that handles routing, authentication and rate limiting, then stateless services scaled horizontally in containers (Docker with Kubernetes autoscaling) and found through service discovery.
  3. Choose communication per interaction. Use synchronous REST or gRPC when the caller needs an answer now. Use asynchronous events over a broker such as Kafka or RabbitMQ for everything else. Handle cross-service workflows with sagas and compensating actions, and with the transactional outbox pattern, rather than two-phase commit.
  4. Design for partial failure: timeouts on every call, retries with exponential backoff and jitter only for idempotent operations or those carrying an idempotency key, circuit breakers (Resilience4j in a Spring Boot stack) and bulkheads. Put a cache such as Redis in front of hot reads.
  5. Cover operations: centralized logs, metrics, and distributed tracing with correlation IDs (OpenTelemetry), plus an independent CI/CD pipeline and versioned API for each service.

Follow-up

  • The payment succeeds but the inventory service fails mid-checkout. How does your design reach a consistent state?
  • Where is the user's token verified: only at the gateway, or in every service as well?
  • At what team size or traffic level would you not use microservices at all?

What considerations would you make for database design in a high-traffic application?

Medium · System Design / Architecture

Approach

  1. Start from the access patterns: the top queries, the read/write ratio and the growth rate. Normalize for write integrity, then denormalize or precompute selectively for the hottest reads.
  2. Index for the queries you actually run. A composite index should match the WHERE columns and then the ORDER BY, following the leftmost-prefix rule; covering indexes avoid going back to the table. Confirm with EXPLAIN, and remember that every extra index slows writes.
  3. Scale reads with connection pooling (HikariCP is Spring Boot's default pool), cache-aside caching with TTLs and explicit invalidation, and read replicas. Replicas lag, so route read-your-own-writes requests to the primary.
  4. Scale writes by batching, by queues that absorb spikes, by partitioning large tables (for example by time) and by sharding on a high-cardinality, evenly distributed key. Say which queries become cross-shard and therefore expensive.
  5. Protect correctness under concurrency. Choose the isolation level deliberately; use optimistic locking with a version column (@Version in JPA) or SELECT ... FOR UPDATE where contention is high; avoid single hot rows such as global counters. Run schema migrations in expand-then-contract steps so they cause no downtime.

Follow-up

  • A query that used to be fast is slow now that the table has ten times the rows. How do you diagnose it?
  • A user updates their profile and immediately sees the old value read from a replica. How do you fix that?
  • How would you choose a shard key for an orders table, and which query does that choice make expensive?

Describe the trade-offs between using a monolithic vs. microservices architecture.

Medium · System Design / Architecture

Approach

  1. Give the monolith's strengths and costs. It is one deployable, with in-process calls, ACID transactions across one database, and simple local debugging and testing. But every change redeploys the whole app, it scales only as one unit, coupling grows over time, and builds get slow.
  2. Give the microservices side. Each service deploys and scales on its own, faults stay isolated, and teams can work on their own services and choose their own stacks. The costs are network latency and partial failure, data consistency across services (sagas, eventual consistency), operational overhead (discovery, tracing, a pipeline per service) and harder integration testing.
  3. Name the middle path: a modular monolith with enforced module boundaries. Extract services later with the strangler fig pattern once a boundary has proven stable.
  4. Give the deciding factors: team size and ownership, how clear the domain boundaries are, whether parts of the system need very different scaling, how often you deploy, and how mature your operations are. Warn against the distributed monolith, where services share a database or have to deploy in lockstep.

Follow-up

  • Which module of a monolith would you extract first, and why that one?
  • A transaction used to span two tables that now belong to two services. How do you keep the data consistent?
  • How do you test the contract between two services without deploying both (for example consumer-driven contract tests)?

How do you ensure security in your applications?

Medium · System Design / Architecture

Approach

  1. Start with a threat model: list the assets, the entry points and the trust boundaries, then work through the OWASP Top 10 as a checklist instead of naming tools at random.
  2. Handle untrusted input safely. Use parameterized queries or prepared statements with bind parameters to prevent SQL injection, encode output for its context to prevent XSS, use CSRF tokens or SameSite cookies when sessions live in cookies, and always validate on the server.
  3. Get authentication and authorization right. Hash passwords with bcrypt or Argon2, never a single fast hash. Add MFA, and use OAuth2/OIDC where it fits. For JWTs, verify the signature and keep expiry short. Check authorization on the server for every resource to prevent IDOR, and grant least privilege. In a Spring stack this is configured in the Spring Security filter chain and method-level rules.
  4. Protect data and the supply chain: TLS everywhere with HSTS, secrets in a secrets manager rather than in the repo, encryption at rest, dependency scanning and patching (OWASP Dependency-Check, Dependabot) and a Content-Security-Policy header.
  5. Detect and respond. Keep audit logs that leave out passwords and tokens, rate-limit logins against brute force, alert on anomalies, and run SAST/DAST in CI alongside code review.

Follow-up

  • How do you store passwords, and why is SHA-256 alone not enough?
  • Where would you keep a token in a browser app: localStorage, with its XSS exposure, or an HttpOnly cookie, which brings CSRF to handle?
  • How would you look for an IDOR in an existing REST API?

Explain how you would approach load balancing and performance tuning.

Medium · System Design / Architecture

Approach

  1. Explain the load balancer layers. L4 balancers route by IP and port at the TCP level. L7 balancers route by HTTP path or header and can terminate TLS. Name the algorithms and when each fits: round robin or weighted round robin for uniform requests, least connections for uneven request cost, and consistent hashing when a key must stick to one node (caches).
  2. Cover availability: active and passive health checks that pull unhealthy instances out of rotation, connection draining during deploys, and stateless app servers with sessions moved to a store such as Redis, so you do not need sticky sessions.
  3. Run tuning as a loop. Set targets (p95/p99 latency, throughput), reproduce the load with JMeter, Gatling or k6, find the saturated resource (CPU, heap and GC, the database, a thread or connection pool) from metrics and profiles, then change one thing at a time and measure again.
  4. List the usual levers in order of payoff: query and index fixes, caching (CDN and application cache), moving slow work to queues, right-sizing thread and connection pools, autoscaling, and JVM heap or GC tuning.
  5. Size pools with Little's law: requests in flight equal arrival rate times average latency (L = λW). Adding threads past the database's capacity only moves the queue somewhere else.

Follow-up

  • Traffic is spread evenly, but one instance shows much higher latency than the others. What do you check?
  • How would you size the database connection pool for a service under a given load?
  • When would you choose consistent hashing over least connections?

Exports duplicate a row range about once a week

Hard · leases · clock skew · idempotency

Roughly once a week an export writes a file containing a duplicated range of rows. The affected job_run rows show attempt = 1, status = succeeded, one started_at, and a lease_owner naming a different host from the one whose logs show the job starting. Leases last 30 seconds and are heartbeated every 10 from inside the handler; lease_expires_at is computed on the worker and compared against the database's now(). Find the mechanism, and give a fix that holds even if you cannot fix the clocks.

Approach

  1. Start from the fact that eliminates the obvious answer. attempt = 1 means no retry was recorded, so this is not a re-run after failure; two workers ran the same row concurrently and the takeover path never touched the counter. lease_owner naming a host other than the one that started the job is the same statement from the other side.
  2. Enumerate the mechanisms that cause a premature takeover, then find the signal that separates them. Either the lease genuinely expired because the heartbeat did not fire, which is what happens when the heartbeat runs on the handler's own thread and the handler makes a long blocking call, or it only appeared expired because two clocks disagree, since lease_expires_at is written from the worker's clock and evaluated against the database's. The discriminator is the distribution: incidents clustered on the longest exports indict the heartbeat, incidents clustered on one host indict skew. Measure both, and measure each host's offset against the database directly.
  3. Read the reclaim query precisely. In PostgreSQL now() is transaction start time, not statement time, so a reclaimer holding a long transaction compares against an older timestamp than expected; clock_timestamp() is the statement-time function. This is worth ruling in or out before you redesign anything, because it changes which rows look expired.
  4. Remove the second clock rather than trying to synchronise it. Issue and extend the lease in the database, with lease_expires_at = now() + interval '30 seconds' in both the claim and the heartbeat, so exactly one clock is ever compared and worker skew stops mattering to this predicate.

Follow-up

  • The displaced worker has already streamed half the file to object storage. What makes that side effect safe to repeat?
  • You now count takeovers. What alert fires on that counter, and at what threshold?

Suggested practice checklist

The plan follows the three reported rounds and the Java and Spring topic breakdown: fundamentals first, then coding drills, then databases, APIs and architecture, ending on behavioral stories and a spoken run-through.

Day 1 — Map the loop and inventory your stack

  • Write the three reported rounds (Preliminary Screening, Coding Interview, Behavioral Interview) with the question types each covers, and mark your weakest
  • List each requirement from the role (Java, C# or Python; Spring or .NET; SQL and NoSQL; Git; CI/CD) and write one project where you used it
  • Record yourself giving a two-minute walkthrough of your most relevant project

Deliverable: A one-page round map with your weakest round marked, a stack inventory with one project per requirement, and one recorded project walkthrough.

Day 2 — Java, OOP and Spring fundamentals

  • Write four short Java examples, one each for encapsulation, inheritance, polymorphism and abstraction, and one case where composition is better than inheritance
  • Explain in writing what a Spring bean is, constructor versus field injection, and what Spring Boot auto-configuration replaces
  • Write a synchronous and a CompletableFuture version of the same two-service call, and note where blocking happens and where exceptions surface

Deliverable: Four OOP code examples, a half-page Spring container and Boot explanation in your own words, and two versions of the service-call example with notes.

Day 3 — Coding drills with narration

  • Write reverse a linked list iteratively and recursively, and test on empty, single-node and three-node lists
  • Write binary search twice (inclusive bounds and half-open), then a first-occurrence variant for duplicates
  • Write merge of two sorted arrays with two pointers, then solve one LeetCode medium on a hash map, stack or heap while speaking your reasoning aloud

Deliverable: Working, tested code for the linked-list reversal, both binary search forms and the merge, plus one narrated medium solution with its stated complexity.

Day 4 — Performance and databases

  • Take one slow function you wrote, profile or reason about the hotspot, and write the before and after with complexity
  • Write a one-page comparison of SQL and NoSQL covering schema, transactions, scaling and query flexibility, with an example workload for each
  • Solve the soft-deleted accounts SQL exercise from the practice set and note which index supports it
  • Write the checklist you would apply to a high-traffic database: indexes, read replicas, caching, partitioning, connection pooling

Deliverable: A before-and-after optimization with complexity notes, a SQL versus NoSQL comparison page, a solved SQL practice exercise, and a database design checklist.

Day 5 — APIs, errors, security and debugging

  • Design a REST API for orders with line items on paper: resources, verbs, status codes, pagination and one error body shape
  • Write the error-handling plan for a Spring Boot service: exception types, @ControllerAdvice mapping, transaction rollback, logging, timeouts and retries
  • Write a security checklist: authentication, authorization, input validation, parameterised queries, secrets handling, dependency updates
  • Work the duplicated-export-rows debugging exercise from the practice set, writing your investigation order before you look for the fix

Deliverable: An API design sheet, an error-handling plan, a security checklist and a written debugging sequence for the practice exercise.

Day 6 — Architecture trade-offs

  • Draw a microservices layout for a web application: services, data ownership, gateway, messaging, and where you would keep a monolith instead
  • Write the monolith versus microservices trade-off in two columns with a team-size and deployment-frequency argument
  • Write a load balancing and tuning outline: algorithms (round robin, least connections), health checks, caching, connection pools, and how you would measure before changing anything
  • Explain the design aloud, covering what breaks first at ten times traffic

Deliverable: One microservices diagram, a two-column trade-off sheet, a load balancing and tuning outline, and a recorded spoken explanation.

Day 7 — Behavioral stories and a full run-through

  • Write three stories (challenging project, team conflict, feedback received) in situation, action, result form with a measurable outcome each
  • Prepare the prioritization and motivation answers, each tied to a specific example
  • Run a spoken pass through the weakest coding question, the weakest architecture question and all five behavioral prompts, and note anything you hesitated on

Deliverable: Three written stories, two prepared answers, and a hesitation list from the full spoken run-through to revisit before the interview.

Behavioural preparation

Candidates describe the Behavioral Interview as centred on cultural fit and team dynamics. For this role, that means examples of working with product managers, designers and other engineers, taking part in code reviews, and handling change or ambiguity. Prepare real stories where your own decision is visible.

  1. Tell a story about a time requirements changed midway, and what you did to keep the work moving.

How do you handle error management in your applications?

Medium · Technical / Domain Questions

Approach

  1. Answer from a service you built: separate expected failures (validation errors, not found, conflicts) from unexpected ones, and say which become typed results or 4xx responses and which propagate as exceptions.
  2. In Java, state your rule: checked exceptions for recoverable conditions the caller must handle, unchecked exceptions for programming errors, never an empty catch block, and wrap with the original cause so the stack trace survives.
  3. Centralise translation at the edge. In a Spring Boot service, a @ControllerAdvice class with @ExceptionHandler methods maps exceptions to one consistent error body and status code, so controllers stay free of try/catch blocks.
  4. Log once, at the boundary, with a correlation id and the inputs that matter, and keep secrets and personal data out of messages. Mention transactions: @Transactional rolls back on unchecked exceptions by default, so a failure does not leave half-written state.
  5. For calls to other services, add timeouts, bounded retries with backoff only on idempotent operations, and a fallback or circuit breaker. Close with one real incident where a missing timeout or swallowed exception caused harm and what you changed afterwards.

Follow-up

  • Does a checked exception roll back a Spring @Transactional method by default?
  • How do you stop a retry from charging a customer twice?
  • What does the client receive for a failure, and what do you only log?

Describe your experience with RESTful APIs and how you would design one.

Medium · Technical / Domain Questions

Approach

  1. Begin with one API you actually built or consumed: who the clients were, what resources it exposed, and one design decision you would defend. The "how would you design one" half needs a concrete example, such as orders with line items.
  2. Model nouns rather than actions: /orders and /orders/{id}, using GET, POST, PUT, PATCH and DELETE by their semantics. GET is safe, PUT and DELETE are idempotent, and POST creates and is not idempotent unless the client sends an idempotency key.
  3. Choose status codes deliberately: 201 with a Location header on create, 204 on delete, 400 or 422 for validation failures, 401 versus 403, 404, 409 for conflicts, and one error body shape across the whole API.
  4. Cover collections: filtering and sorting parameters, pagination (cursor-based for large or changing data, offset for small stable sets) and a cap on page size.
  5. Finish with versioning (path or header, and additive changes that avoid a new version), authentication, and an OpenAPI description so clients and tests share one contract.

Follow-up

  • PUT or PATCH to change a single field, and why?
  • How would you paginate a feed where new rows arrive constantly?
  • How do you ship a breaking change without breaking existing clients?

Describe a challenging project you worked on and how you overcame obstacles.

Medium · Behavioral / Leadership

Approach

  1. Choose a project whose difficulty was specific: a migration, a performance problem, an unclear specification, a hard integration. Name it in one sentence and give the stake in another, then move on.
  2. Use situation, task, action, result, but spend most of the time on your own actions: the options you weighed, why you picked one, and what you built or changed.
  3. Present the obstacles as a sequence: the first blocker, what you did about it, what then surfaced. This shows a repeatable way of working rather than a single lucky fix.
  4. Give a result you can defend with a number: latency, defect count, delivery date, hours saved. If no metric exists, name the observable change and who noticed it.
  5. End with what you would do differently. A story that rests on heroics alone, or where the obstacle was entirely someone else's fault, answers a different question.

Follow-up

  • What was the hardest decision, and which options did you rule out?
  • Which part was your own work and which the team's?
  • What would you do differently if you ran the project again?

How do you prioritize tasks when working on multiple projects?

Medium · Behavioral / Leadership

Approach

  1. Give the method before the story: list the work, estimate effort, and rank by impact, deadline and who is blocked. Name a concrete mechanism, such as a written backlog, a ranked list agreed with the product manager, or a daily check of what slips.
  2. Show the conflict case: two requests of equal urgency from different people. The strong version is that you took the trade-off back to them with cost and options, rather than quietly dropping one.
  3. Include interruptions: how a production bug or review request is triaged against planned feature work, and what you explicitly defer and tell people about.
  4. Close with the result: what shipped, what slipped, and how early you communicated it. Answering that you simply work longer hours does not describe a method.

Follow-up

  • What do you do when your manager and a product manager give conflicting priorities?
  • How do you handle a task that keeps getting deferred?
  • How do you estimate when the scope is still unclear?

Can you give an example of how you handled a conflict within a team?

Medium · Behavioral / Leadership

Approach

  1. Pick a real disagreement with a peer over a technical or process choice, such as an API shape, review feedback or who owns a task. Avoid a personality clash you never addressed directly.
  2. Describe how you moved it to facts: you asked what each side was optimising for, wrote the options down, ran a small spike or pulled data, and brought in a third person only after talking to the colleague directly.
  3. State the outcome honestly, including where you were wrong or compromised, and show that you committed to the decision once it was made.
  4. End with the working relationship afterwards and one habit you kept, such as writing design decisions down. A story that casts the other person as the villain tends to sink the answer.

Follow-up

  • What if the other person had been more senior than you?
  • What would you have done if the disagreement had stayed unresolved?
  • Did the decision turn out to be right?

What motivates you to succeed in your career?

Medium · Behavioral / Leadership

Approach

  1. Give two or three specific drivers drawn from work you have done, such as learning a stack deeply, owning a service end to end, or seeing users rely on something you shipped, and anchor each in a concrete moment.
  2. Connect them to the role as candidates describe it: working with product managers and designers, taking part in code reviews, troubleshooting existing applications, and a Java and Spring stack. Say it only where it is true for you.
  3. Show the driver in behaviour: a time it made you do something costly, such as learning a framework on your own time, volunteering for a hard bug, or mentoring a newer colleague.
  4. Avoid answers that fit any employer (money, passion, growth) and avoid a career plan that has no place for this job.

Follow-up

  • When were you least motivated at work, and what did you do about it?
  • What would make you leave a role?
  • Which part of this job would excite you least?

How do you approach feedback and continuous improvement?

Medium · Behavioral / Leadership

Approach

  1. Lead with one specific piece of feedback you received, for example a code review comment or a performance conversation, and say how it landed without defending yourself.
  2. Show the action and a signal that it worked: smaller pull requests, tests written before review, a short design note before coding, then fewer review rounds or fewer regressions.
  3. Cover the other direction too: feedback you gave in code review, aimed at the code with a concrete suggestion. Code reviews are among the reported responsibilities of the role.
  4. Name an ongoing improvement mechanism: retrospectives, reading other people's reviews on your team, or a skill goal with a date. Avoid a story in which the feedback was secretly praise.

Follow-up

  • Tell me about feedback you disagreed with and what you did.
  • How do you give hard feedback to a peer?
  • What are you working on improving right now?