cswork / libraryOpen practice workspace

Interview guides · Abhibus

Abhibus Software Engineer Interview Guide

Abhibus Software Engineer interview guide: two reported rounds, OOP, REST, coding and behavioral questions, and a 7-day plan.

The 60-second brief

Abhibus is a travel company. Candidates describe the Software Engineer role as work on real-time applications, with backend systems behind user-facing front-end screens. Example projects they mention are tuning a booking engine and building APIs that connect to third-party services. The responsibilities reported for the role are building new features and improving existing ones using user feedback, working with product and design teams, reviewing code, and taking part in architecture discussions.

This guide is for candidates interviewing for a Software Engineer position at Abhibus. It covers both reported rounds and all fifteen reported questions: OOP versus functional programming, REST design, a past bug, performance and scalability, version control, high latency, shortest path, multi-service features, three behavioral prompts, millions of concurrent users, SQL versus NoSQL, reversing a linked list, and sorting and merging arrays. The requirements candidates describe mention Java, SQL and NoSQL databases, REST and microservices, and roughly 3-5 years of development experience.

Candidates report two rounds over about 2-4 weeks: a Technical Discussion with technology-specific questions and practical assessments, then a Managerial Round about previous projects and the challenges in them.

Focus areas

  • Object-Oriented Programming (OOP)
  • Pagination
  • OOP Concepts (e.g., Encapsulation/Inheritance/Polymorphism)

Overview

The work candidates describe is backend-heavy and service-oriented: real-time applications, booking-engine optimisation, and APIs that talk to third-party services. The requirements they list are Java and its frameworks, SQL and NoSQL databases, REST API design, microservices and agile practice, with AWS or Azure and React or Angular named as extras. That mix tells you where to spend time: be able to write Java, sketch a schema, design an endpoint, and explain what happens when one service in a chain is slow or down.

The reported questions fall into five groups. Technical and domain questions ask for OOP versus functional programming, RESTful API design, a challenging bug you fixed, how you keep applications fast and scalable, and why version control matters. Problem-solving questions cover diagnosing a high-latency service, the shortest path in a graph, and building a feature that needs data from several services. Two design questions ask about millions of concurrent users and SQL versus NoSQL. Two coding questions are reversing a linked list and sorting and merging two arrays. Three behavioral prompts cover leading a project, team conflict and adapting to change. Pagination, logical reasoning and Java also appear among the reported topics.

Most of these are spoken-answer questions, so the preparation is concrete examples rather than definitions. For each concept question, have a short Java or SQL snippet ready. For the coding questions, practise writing working code from a blank editor, because the Technical Discussion is reported to include practical assessments. For the Managerial Round, which is reported to be a discussion of previous projects and challenges, build a small dossier on two projects: the architecture, one bug, one performance problem, one disagreement and one change of plan. The same material then serves the bug question, the performance question and all three behavioral prompts.

The Abhibus interview process

Candidates describe two stages, a Technical Discussion first and a Managerial Round second. The round names and order are what candidates report, not a published process.

Technical Discussion

Candidates report this round as technology-specific questions combined with practical assessments. The reported stack is Java and its frameworks plus SQL and NoSQL databases, and the reported topics include OOP concepts, pagination, logical reasoning and Java. Approach it by pairing every concept answer with something concrete: a few lines of Java, a table or query, or a request and response for an endpoint. Practise the coding questions on a blank editor and say the complexity when you finish, because practical assessments reward code that runs.

What to demonstrate

  • Working knowledge of Java and the frameworks around it
  • Database knowledge across SQL and NoSQL, including how you would query and page through data
  • OOP concepts such as encapsulation, inheritance and polymorphism, a reported topic
  • Practical assessment output: code that compiles and handles edge cases

How to prepare

  • Write one small task in loop style, class-and-interface style and stream style in Java, then explain what OOP and functional programming each do better.
  • Sketch a REST API for one resource with URLs, methods, status codes, an error format and paginated list responses.
  • Write iterative and recursive linked-list reversal, and a two-pointer merge of sorted arrays, from a blank editor with edge-case tests.
  • Rehearse a diagnosis order for a slow service and a SQL versus NoSQL comparison tied to two named access patterns.

Managerial Round

Candidates report this round as a discussion of previous projects and the challenges faced in them, framed as experience and cultural alignment. Because the content is your own history, the preparation is a project dossier: what you built, your part in it, what went wrong, and what you changed afterwards. Bring concrete details such as the bug's root cause, the numbers you measured, or the decision you argued for, and keep each story to a clear beginning, action and result.

What to demonstrate

  • How clearly you narrate a previous project and its challenges
  • Your own contribution and decisions inside team work
  • Experience and cultural alignment as the round is described by candidates
  • Teamwork examples such as leading, resolving a conflict and adapting to change

How to prepare

  • Write a dossier for two projects covering the problem, architecture, your role, one bug, one performance issue, one disagreement and one change of plan.
  • Outline STAR answers for leading a project, handling team conflict and adapting to a significant change, each with a measured or observable result.
  • Turn your hardest bug into a story with symptom, investigation steps, root cause, fix and prevention.
  • Prepare a few questions about the team's review, release and architecture-discussion practices to ask at the end.

Where candidates lose points

Defining OOP and functional programming as lists of vocabulary with no code

Prepare one small example, such as filtering and totalling a list of records, written in mutable loop style, with classes and interfaces, and with Java streams on immutable data. Compare state, side effects, testability and where polymorphism helps. Say when you would pick each, instead of declaring a winner.

Designing a REST API with verbs in the URLs and no thought for lists, errors or retries

Use nouns for resources, the right HTTP methods and status codes, a consistent error body and versioning. Explain how list endpoints are paginated: offset for simple pages, keyset or cursor for large or changing data. Say which operations must be idempotent so a retry cannot create a duplicate.

Answering the high-latency question with a fix, such as adding a cache, before measuring anything

Give an order: confirm the symptom and its scope, compare percentiles before and after any change, split time across hops with traces or logs, then check dependency calls, database queries with EXPLAIN, thread pools, garbage collection and recent deployments. Name the fix only after the evidence points to it.

Producing linked-list, merge or shortest-path code that fails on the first edge case

For reversal, hold the next node before you repoint, and test an empty list, one node and two nodes. For merging, append the leftover tail of whichever array remains. For shortest path, use breadth-first search only when edges are unweighted, Dijkstra for non-negative weights, and say what breaks with negative weights.

Telling the bug, leadership, conflict or change stories as team narratives where your own actions cannot be found

Write each story in STAR form with sentences starting with 'I'. Include the specific decision you made, what you measured, the result and what you changed afterwards, and rehearse them aloud so the two or three projects in your dossier cover all four prompts.

Questions & practice

Write a function to reverse a linked list.

Medium · Coding / Algorithms

Approach

  1. Iterative with three pointers: prev = null, curr = head; in the loop save next = curr.next, set curr.next = prev, then advance prev = curr and curr = next; return prev as the new head. O(n) time, O(1) extra space.
  2. Recursive alternative: reverse the rest, then set head.next.next = head and head.next = null. Also O(n) time, but it uses O(n) call-stack space, so a very long list can throw StackOverflowError in Java.
  3. Handle edge cases explicitly: empty list (null head), a single node, two nodes; always save next before overwriting the pointer, and return the new head rather than the old one.
  4. Test by walking the result and checking the order and that the old head's next is null, so no cycle remains.
  5. Know the common variants: reverse between positions left and right, reverse in groups of k, a doubly linked list (swap prev and next on each node), and a palindrome check that reverses the second half.

Follow-up

  • Reverse only the nodes between positions left and right in one pass.
  • Reverse the list in groups of k, leaving any remainder as it is.
  • What exactly goes wrong if you overwrite curr.next before saving it?

Solve a problem involving sorting and merging two arrays.

Medium · Coding / Algorithms

Approach

  1. Clarify the input first: are both arrays already sorted, should duplicates be kept, must the merge happen in place (e.g. the first array has spare slots at the end), and what output is expected.
  2. If both are sorted, merge with two pointers in O(m+n) time. For an in-place merge into the first array, fill from the back (i = m-1, j = n-1, k = m+n-1) so no unread value is overwritten, and stop once the second array is used up.
  3. If they are unsorted, concatenate and sort in O((m+n) log(m+n)), or sort each and then merge. In Java, Arrays.sort on objects uses TimSort, which is stable; on primitives it uses dual-pivot quicksort.
  4. Edge cases: one array empty, every value of one array smaller than the other, duplicates, negative values.
  5. Know the neighbours: merging overlapping intervals (sort by start, then extend or append) in O(n log n), intersection or union of sorted arrays with two pointers, k sorted arrays with a min-heap in O(N log k), and the median of two sorted arrays by binary search in O(log(min(m,n))).

Follow-up

  • Merge k sorted arrays efficiently.
  • Find the median of two sorted arrays without merging them.
  • How would you sort and merge data too large to fit in memory?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Discuss the trade-offs between SQL and NoSQL databases in a given application.

Medium · System Design / Architecture

Approach

  1. Decide from access patterns and consistency needs. Relational databases give a schema, joins, secondary indexes, ad hoc queries and multi-row ACID transactions, which suits orders, payments and inventory where invariants must hold.
  2. Name the NoSQL families and fits: key-value (Redis, DynamoDB) for sessions and caches, document (MongoDB) for self-contained aggregates, wide-column (Cassandra) for high write volume, graph databases for relationship traversal. They are designed around known queries and denormalised data.
  3. State the scaling trade-off: relational databases scale reads with replicas (with replica lag), but sharding writes is manual; most NoSQL stores partition natively but limit cross-partition joins and transactions.
  4. Explain tunable consistency: under a network partition a system favours consistency or availability (CAP); in Cassandra, choosing R + W > N replicas makes every read overlap the latest acknowledged write.
  5. Give a concrete split and its cost: bookings and payments in PostgreSQL or MySQL, sessions in Redis, search in Elasticsearch. Each extra store adds operations work, and a flexible schema moves validation into application code.

Follow-up

  • How would you model a many-to-many relationship in a document store?
  • What do primary and foreign keys guarantee, and what do you lose without foreign keys?
  • How would you find out why a SQL query is slow and fix it?

Denormalise tenant onto revisions and backfill it live

Hard · denormalisation · online migration · backfill

resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.

Approach

  1. Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
  2. Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
  3. Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
  4. Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.

Follow-up

  • The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
  • How do you verify the backfill actually finished, given rows are still being inserted while it runs?

What are the key differences between Object-Oriented Programming and Functional Programming?

Medium · Technical / Domain Questions

Approach

  1. Contrast the unit of design: OOP bundles state with the methods that change it behind an interface (encapsulation, inheritance, polymorphism through dynamic dispatch); FP builds programs from pure functions over immutable values, composed with higher-order functions.
  2. Explain the state trade-off: shared mutable object state needs locking under concurrency, while pure functions are referentially transparent, so they are easier to unit test, cache and run in parallel.
  3. Name the extension trade-off (the expression problem): in OOP a new type is just a new subclass, but a new operation touches every class; with sealed types and pattern matching the reverse holds.
  4. Ground it in Java: lambdas and functional interfaces (Function, Predicate), the Streams API (map, filter, reduce), records and List.of for immutability. Show one loop rewritten as a stream and say when the loop is clearer.
  5. Close with costs: immutability means extra allocation, side effects inside a stream's map or forEach break the model, and deep inheritance hierarchies are brittle, so prefer composition over inheritance.

Follow-up

  • Is a Java stream pipeline lazy, and what makes it actually run?
  • How would you make a Java class fully immutable, including a List field?
  • When would you pick composition over inheritance, with an example?

Can you explain the concept of RESTful APIs and how you would design one?

Medium · Technical / Domain Questions

Approach

  1. Define REST by its constraints: client-server, stateless requests (each carries its own auth, such as a bearer token), cacheable responses, a uniform interface and a layered system; resources are nouns at URIs, exchanged as representations such as JSON.
  2. Map methods to semantics: GET is safe and idempotent, PUT replaces and is idempotent, PATCH updates part of a resource, POST creates and is not idempotent, DELETE is idempotent. Return 201 with a Location header on create, 204 on empty success.
  3. Use status codes precisely: 400 bad input, 401 unauthenticated vs 403 forbidden, 404, 409 conflict, 429 rate limited, 5xx for server faults, with a consistent error body.
  4. Design list endpoints with pagination: offset/limit is simple but slows as OFFSET grows and skips or repeats rows when data changes; cursor (keyset) pagination filters on the last seen sort key, e.g. WHERE (created_at, id) < (?, ?) ORDER BY created_at DESC, id DESC LIMIT n.
  5. Cover the rest: versioning (/v1 in the path or a header), idempotency keys so a retried POST does not create a duplicate, authentication, rate limiting and documenting the contract with OpenAPI.

Follow-up

  • A client's POST timed out; how does it retry without creating the resource twice?
  • Why can offset pagination show the same item twice, and how does a cursor fix it?
  • How would you evolve a response field without breaking existing clients?

Describe a challenging bug you encountered in your previous projects and how you resolved it.

Medium · Technical / Domain Questions

Approach

  1. Pick a bug with a non-obvious mechanism (a race condition, a timezone or DST error, stale cache, connection-pool exhaustion, an N+1 query) and give the symptom and its impact in one or two sentences.
  2. Walk the debugging sequence: reproduce it, or narrow it with logs and metrics when you cannot; form hypotheses and eliminate them with evidence, using tools such as git bisect, targeted logging, a Java thread dump (jstack) or heap dump, or a diff of a failing request against a passing one.
  3. State the root cause as a mechanism ("two threads read the same counter before either wrote it"), not "it was a config issue".
  4. Finish with fix and prevention: a regression test that failed before the fix, a metric or alert, and why the existing tests missed it.
  5. Make your own part explicit: say "I" for what you did, and avoid stories where a restart was the fix or someone else found the cause.

Follow-up

  • How did you confirm the fix worked in production, not only on your machine?
  • If you could not reproduce it locally, what would you have done next?
  • What would have caught this bug before release?

How do you ensure the performance and scalability of your applications?

Medium · Technical / Domain Questions

Approach

  1. Start from targets and measurement: define p95/p99 latency, throughput and error-rate goals, profile before optimising (JFR or async-profiler for Java, EXPLAIN ANALYZE for queries) and load test with a tool such as JMeter, Gatling or k6.
  2. Fix the data layer first: indexes that match query predicates, removing N+1 queries (fetch joins or batch fetching in JPA/Hibernate), a sized connection pool such as HikariCP, read replicas for read-heavy traffic and paginated rather than unbounded result sets.
  3. Add caching with a stated staleness budget: cache-aside in Redis with a TTL plus explicit invalidation on writes, and HTTP or CDN caching for static and public responses.
  4. Scale out: keep app servers stateless behind a load balancer, move sessions to tokens or a shared store, and push non-urgent work (emails, notifications) onto a queue.
  5. Protect under load: timeouts on every remote call, bounded retries with exponential backoff and jitter, circuit breakers and rate limiting; then re-measure to prove the change moved the metric.

Follow-up

  • Why track p99 latency rather than the average?
  • How do you keep a cached value correct when the underlying row changes?
  • What happens to the database when you add ten more app servers?

What is the significance of version control in software development?

Medium · Technical / Domain Questions

Approach

  1. Name what it provides: a full history of who changed what and why, safe reverts, parallel work on branches and merging; with Git, every clone holds the full history.
  2. Describe a team workflow: short-lived feature branches, pull requests with code review and CI checks before merge; contrast trunk-based development with GitFlow's long-lived release branches and the merge-conflict cost of long branches.
  3. Explain merge vs rebase: merge keeps history and adds a merge commit, rebase rewrites commits into a linear history, so never rebase a branch others have already pulled.
  4. Show recovery tools: git revert adds a new commit that undoes a change (safe on shared branches), git reset moves the branch pointer and rewrites history, git reflog recovers lost commits, git bisect binary-searches history to find the commit that introduced a bug.
  5. Cover release hygiene: small atomic commits with clear messages, tags for releases, and if a secret is committed, rotate it, because deleting the file leaves it in history.

Follow-up

  • You pushed a bad commit to the shared main branch: revert or reset, and why?
  • How do you resolve a merge conflict and confirm the merged code is correct?
  • Which branching strategy suits a team that deploys several times a day?

Given a scenario where a service is experiencing high latency, how would you diagnose the issue?

Medium · Problem-Solving / Case Studies

Approach

  1. Scope it before touching anything: which endpoints, which percentile moved (p50 or only p99), since when, on every host or a few, and whether it lines up with a deploy, a traffic spike or a dependency change.
  2. Localise with tracing: distributed traces (e.g. OpenTelemetry) split a request into spans and show whether time goes to app code, the database, a downstream call or waiting in a queue.
  3. Check saturation on the slow tier: CPU, memory and GC pause logs for a Java service, thread-pool and connection-pool waits (HikariCP pending threads), and a thread dump for threads blocked on locks or I/O.
  4. Check the database: slow-query log, EXPLAIN ANALYZE for sequential scans from a missing index, lock contention, and N+1 query patterns introduced by a recent change.
  5. Mitigate, then fix: roll back a correlated deploy, scale out or shed load to restore service, then fix the root cause and add an alert on p99 latency. If only some users are slow, suspect a hot key, a region or one bad instance.

Follow-up

  • p50 is unchanged but p99 tripled: what does that point to?
  • A downstream dependency slows and your request threads pile up; how do you protect the service?
  • How would you tell GC pauses apart from slow queries using only metrics?

Design an algorithm to find the shortest path in a graph. What considerations would you make for performance?

Medium · Problem-Solving / Case Studies

Approach

  1. Clarify the graph first: weighted or not, directed or not, negative weights possible, single-source or all-pairs, and roughly how many vertices and edges (sparse or dense).
  2. Pick by those answers: BFS for unweighted graphs in O(V+E); Dijkstra with a binary heap for non-negative weights in O((V+E) log V); Bellman-Ford for negative weights in O(V·E), which also detects negative cycles; Floyd-Warshall for all-pairs on small dense graphs in O(V^3); 0-1 BFS with a deque when weights are only 0 or 1.
  3. Implement Dijkstra on an adjacency list: a dist array set to infinity, a parent array to rebuild the path, and early exit when the target is popped. Java's PriorityQueue has no decrease-key, so push a new entry and skip popped entries whose distance is stale.
  4. For performance: A* with an admissible heuristic (e.g. straight-line distance on a map) explores fewer nodes, bidirectional search roughly halves the frontier, and repeated queries on a static graph justify precomputation or caching.
  5. Edge cases: unreachable target, source equal to target, parallel edges between the same pair, and overflow when summing large weights (use long in Java).

Follow-up

  • Why does Dijkstra give wrong answers with negative edge weights?
  • How would you minimise the number of stops first and total cost second?
  • How would you serve many route queries per second on a graph that rarely changes?

How would you approach implementing a new feature that requires data from multiple services?

Medium · Problem-Solving / Case Studies

Approach

  1. Clarify ownership and needs: which service owns each piece of data, how fresh it must be, the latency budget, and whether the feature only reads or also writes across services.
  2. For reads, compose in one layer (an aggregator service or backend-for-frontend) that calls the services in parallel (CompletableFuture in Java) with a timeout on each call.
  3. Plan for partial failure: mark each piece of data required or optional, return a degraded response when an optional call fails, retry only idempotent calls with backoff, and add a circuit breaker or a cached fallback.
  4. If the feature needs joins or filtering across services on a hot path, keep a local read model fed by events (CDC or a message broker): lower latency and less coupling, at the cost of eventual consistency.
  5. For writes across services there is no single ACID transaction: use a saga with compensating actions, the transactional outbox pattern to publish events reliably, and idempotent consumers; propagate a trace ID and roll out behind a feature flag.

Follow-up

  • One dependency becomes slow at p99: what does your feature return?
  • How do you keep the local read model correct if an event is lost or delivered twice?
  • How would you test this flow without running every service locally?

How would you design a system to handle millions of concurrent users?

Medium · System Design / Architecture

Approach

  1. Pin down requirements and estimates: read/write ratio, peak requests per second (concurrent users times requests per user per second), data size, latency target, and which data must be strongly consistent (seat or inventory counts) versus allowed to be stale (search results).
  2. Edge and app tier: DNS and a CDN for static and cacheable content, load balancers, stateless app servers that autoscale horizontally, and sessions held in tokens or a shared store rather than server memory.
  3. Data tier: cache-aside in Redis for hot reads, a primary database with read replicas, and partitioning by a key that spreads load evenly (e.g. user id), stating which cross-partition queries that makes expensive.
  4. Contended writes: for a scarce resource such as the last seat, use one authoritative store with a conditional update (UPDATE ... WHERE available > 0), row locks, or optimistic concurrency with a version column, plus short-lived holds that expire.
  5. Resilience: queues for non-critical work like notifications, rate limiting, circuit breakers, redundancy across availability zones and dashboards on latency and errors. If "concurrent" means open WebSocket connections, size servers by connection count.

Follow-up

  • Two users try to book the last seat at the same moment: how do you prevent overselling?
  • The cache cluster restarts and every request hits the database: how do you avoid a stampede?
  • One partition becomes hot; how do you rebalance it?

Edge instances grow 400 MB per hour until the nightly restart

Hard · memory leak · heap analysis · metric cardinality

Edge API instances start at 700 MB resident and grow about 400 MB/hour; a nightly rolling restart has hidden it for weeks. Growth continues unchanged when request rate halves overnight, p99 degrades in the last hours before an instance is recycled, and heap used immediately after a forced full GC rises monotonically. The service holds no product state. Name the discriminating measurement that separates the plausible causes, give the most likely cause, and give the fix and how you would verify it.

Approach

  1. Separate resident memory from live heap first, because they fail differently. Resident size can grow from fragmentation, native buffers or thread stacks while the heap is flat; heap used after a full GC rising monotonically is the measurement that says objects are reachable and not being released. You already have it, so this is retention, not fragmentation, and that closes off half the candidate list.
  2. Use the rate's independence from traffic as the discriminator. Growth that continues at half the request rate rules out per-request objects that are merely slow to collect and points at a structure that grows with distinct values observed rather than with call volume. Write the candidates that have that property: a metrics registry keyed on a high-cardinality label, an unevicted cache, an interner, a per-key lock map.
  3. Take two heap snapshots an hour apart and diff by retained size, reading the dominator tree, not by allocation count or instance count. Expect one root holding a map with millions of entries, then follow the reference chain to the code that inserts and never removes. Allocation profilers point at churn, which is the wrong signal here.
  4. The candidate that fits this service is an observability label carrying an identifier, such as a request path recorded before templating so that /v1/resources/48213 becomes its own metric series. That grows with distinct ids seen, is independent of rate, and explains the late p99 degradation, since GC cost rises with the size of the live set.

Follow-up

  • Post-GC heap is now flat but resident size still creeps. What are you looking at, and does it matter?
  • How would you have detected this before an OOM, given the nightly restart masked the trend?

Suggested practice checklist

The plan follows the two reported rounds: days 2 to 6 cover the Technical Discussion topics (OOP, REST and data, coding, debugging, services and scale), and day 7 rehearses the project and behavioral discussion.

Day 1 — Map the loop and inventory the stack

  • Write down the two reported rounds, Technical Discussion then Managerial Round, and what each is reported to cover.
  • Rate yourself 1 to 5 on Java, SQL, NoSQL, REST design, microservices and agile, then list AWS or Azure and React or Angular as extras to skim only if time remains.
  • Choose the two projects you will build your dossier around, and note for each the problem, your role and the architecture.

Deliverable: One page with the two rounds, a rated stack list, and the two chosen projects with problem, role and architecture.

Day 2 — OOP, functional programming and Java fundamentals

  • Implement one small task, such as filtering and totalling a list of records, in a mutable loop, with classes and an interface that has two implementations, and with Java streams on immutable data.
  • Write a short comparison covering state, side effects, testability and reuse, and say when composition is a better choice than inheritance.
  • Give a Java example of each of encapsulation, inheritance and polymorphism.
  • Solve three short logical-reasoning puzzles on paper, since logical reasoning appears among the reported topics.

Deliverable: Three working versions of the same task, a written OOP versus functional comparison, and three solved reasoning puzzles.

Day 3 — REST design, pagination and SQL versus NoSQL

  • Design a REST API for one resource: URLs, methods, status codes, an error format, versioning and an idempotent create.
  • Write the same list query with offset pagination and with keyset pagination on an indexed column, and note the cost of each on a large table.
  • Compare SQL and NoSQL for two named access patterns, covering schema, joins, consistency, scaling and indexing.

Deliverable: An API sketch with the pagination contract, both paginated SQL queries, and a two-pattern SQL versus NoSQL comparison table.

Day 4 — Coding: linked list, merge and shortest path

  • Reverse a singly linked list iteratively and recursively in Java, then test an empty list, one node and two nodes.
  • Merge two sorted arrays with two pointers in linear time, then handle the unsorted case by sorting first and state the extra cost.
  • Solve shortest path with breadth-first search for unweighted edges and Dijkstra with a priority queue for non-negative weights, and state complexity and what changes with negative weights.

Deliverable: Three compiled and tested Java solutions, each with its complexity and an edge-case list.

Day 5 — Diagnose, debug and explain your workflow

  • Write a latency checklist: scope the symptom, compare percentiles, trace time per hop, check dependency calls, run EXPLAIN on slow queries, check thread pools and garbage collection, then review recent deployments.
  • Write your hardest bug as a story with symptom, investigation, root cause, fix and prevention.
  • Prepare a short answer on version control covering branching, review, history for bisecting and reverting.

Deliverable: A latency checklist, a spoken walk-through of the practice debugging question, a written bug story and a short version-control answer.

Day 6 — Services, scale and performance

  • Sketch a feature that needs data from several services: the call flow, synchronous versus asynchronous calls, timeouts, retries with idempotency, caching and what the user sees on partial failure.
  • Outline a design for millions of concurrent users: stateless application tier behind a load balancer, caching, read replicas, queues for slow work and a partition key with its trade-off.
  • Write a half-page answer on keeping applications fast: measure first, load test, fix indexes and queries, then cache and scale out.

Deliverable: A multi-service call-flow sketch, a concurrent-user architecture diagram, and a half-page performance and scalability answer naming three concrete measures.

Day 7 — Managerial Round rehearsal

  • Write STAR outlines, in the first person, for leading a project, handling team conflict and adapting to a significant change, each ending in an observable result.
  • Give a spoken walk-through of each dossier project covering the problem, your role, architecture, one bug and one decision you would revisit.
  • Run a mock of the whole round with a friend or a recording, then tighten the stories that sounded vague.
  • List a few questions to ask the team about review, release and architecture-discussion practices.

Deliverable: Three STAR outlines, two project walk-throughs, a recorded or peer mock of the round and a list of questions to ask.

Project stories for the Managerial Round

Candidates report the Managerial Round as a discussion of previous projects and the challenges in them, so behavioral preparation here is mainly project storytelling. The reported prompts cover leading a project, team conflict and adapting to change. Candidate descriptions of the requirements add communication with non-technical stakeholders, working under pressure and agile practice. Prepare stories where you made specific decisions, stated what you measured or observed, and can say what you would change. Reuse the two dossier projects across prompts rather than preparing many thin stories.

  1. How do you handle disagreements with colleagues?
  2. What does teamwork mean to you, and how do you foster it?
  3. Describe your approach to solving a bug that affects multiple users.

Describe a time when you had to lead a project. What challenges did you face, and how did you overcome them?

Medium · Behavioral / Leadership

Approach

  1. Choose a project where you owned scope, planning or delivery, even without a lead title. Open with one sentence stating what you were accountable for, so the story is about your decisions and not the team's activity.
  2. Give the situation and goal in two sentences. Then describe the plan you set: how you broke the work into tasks, who took what, how you tracked progress, and what you set as the review standard.
  3. Name two real challenges and your response to each, for example unclear requirements settled by writing down acceptance criteria, a dependency on another service or team handled with an agreed interface and a mock, or a slipping deadline handled by cutting scope and telling stakeholders early.
  4. Close with the result in observable terms, such as what shipped, defects found afterwards, latency or time saved, and one thing you would change. The mistake that sinks this answer is an all-'we' story where nothing is traceable to you, or a hero story that ignores teammates.

Follow-up

  • How did you split the work and keep track of progress?
  • Tell me about a decision you made as lead that someone disagreed with.
  • What would you do differently if you led it again?

How do you handle conflicts within a team?

Medium · Behavioral / Leadership

Approach

  1. Pick a real, work-level disagreement: an API design, a code review comment, an estimate or a technology choice. A personality clash with no technical content gives you nothing to show.
  2. Show how you handled it: you restated the other person's position until they agreed you had it right, found the actual point of difference, and moved the discussion from opinion to evidence such as a quick prototype, a benchmark, a comparison of trade-offs or a look at production data.
  3. Say how it ended. If the evidence settled it, say whose idea won and that it did not matter. If it stayed stuck, say you took it to the tech lead or manager with both options written down. If you lost, say you committed fully to the decision.
  4. Finish with the working relationship afterwards and one habit you kept. The answer fails if you cast yourself as right and the colleague as the problem, or if you claim you have never had a conflict.

Follow-up

  • What if the person you disagreed with was more senior than you?
  • How would you respond if you still disagreed after a manager made the call?
  • What did you change about how you work with that person or team?

Can you provide an example of a time when you had to adapt to a significant change in a project?

Medium · Behavioral / Leadership

Approach

  1. Pick a change that invalidated work you had already done: a requirement reversal, a scope cut, a technology swap, a new team structure or a moved deadline. A change that cost you nothing shows nothing.
  2. State what stayed fixed and what had to move. Then describe your first steps: listing finished work to keep and to discard, re-estimating, and telling the people affected what would slip, what would be dropped and what risk remained.
  3. Tie it to how you work. Candidates report agile practice as a stated requirement, so you can describe re-prioritising the backlog, shortening the feedback loop, or releasing in smaller pieces after the change.
  4. Give the outcome and the lesson, including what you lost. Avoid answers that reduce to 'I adapted quickly' with no detail, and avoid spending the story complaining about the decision that changed things.

Follow-up

  • What did you drop, and who agreed to that?
  • How did you keep the team and stakeholders informed during the change?
  • Were there early signs of the change you could have caught sooner?