cswork / libraryOpen practice workspace

Interview guides · AIM Specialty Health

AIM Specialty Health Software Engineer Interview Guide

AIM Specialty Health Software Engineer interview guide: Java, REST API build, PHI security, panel and manager rounds, with a 7-day plan.

The 60-second brief

Candidates describe AIM Specialty Health as a specialty benefits management company. The Software Engineer role is described as backend and API integration work on clinical decision-support software. Candidates also report that the platform handles sensitive medical data, so security and HIPAA compliance shape how services are designed, and that the engineering environment mixes older systems being modernized with newer microservices.

This guide is for engineers with roughly 2 to 5 years of experience interviewing for the Software Engineer role. The requirements candidates describe center on core Java, object-oriented design, Spring or Spring Boot, REST APIs and relational databases with SQL; AWS, Docker, microservices and healthcare-data familiarity are listed as extras. It covers all four reported rounds, the reported Java, REST, aptitude and project questions, and a plan that ends with the senior manager conversation.

Candidates report four rounds over about 3 to 5 weeks: an Automated Online Assessment, Technical and Panel Interviews, a Practical Coding Challenge and a Senior Manager Conversation. Candidates say the order can differ between teams and offices.

Focus areas

  • Java programming
  • API development
  • Code test / practical evaluation

Overview

The reported questions cluster around three areas. The first is core Java: HashMap versus ConcurrentHashMap, JVM garbage collection, checked versus unchecked exceptions, polymorphism, and reversing a singly linked list. The second is REST API work: designing an endpoint for multi-step clinical data submissions, choosing status codes, versioning for external clients, securing an endpoint that carries protected health information, and building an API from scratch in Spring Boot or a similar framework. The third is project experience: your most complex system, legacy code, disagreements with product managers and senior leaders, and a production incident.

That mix tells you where to spend time. Java answers should go below the API surface, into what the runtime does with memory and threads, since the reported questions cover garbage collection, concurrent collections and the stack and heap. The API work is practical: candidates describe building a small working service, such as a REST API, so you should be able to stand up controllers, a service layer, persistence and error handling without searching for syntax. Some teams are also reported to ask for code on a whiteboard or paper, so practise without autocomplete.

The healthcare setting changes how you should phrase design answers. When you discuss an endpoint, mention what data it carries, who may call it, what is logged, and how a retried submission is kept from being applied twice. When you discuss legacy code, say how you protected existing behavior while changing it, since candidates report that modernizing older systems alongside new microservices is part of the work. Prepare each story with a concrete decision, the risk you managed and the result.

The AIM Specialty Health interview process

These are the four rounds candidates report. Treat the order as typical rather than fixed, because candidates say it can differ between teams and offices.

Automated Online Assessment

Candidates describe a timed first screen mixing reasoning puzzles with Java comprehension. The early-screening material candidates describe is number and logic puzzles, predicting the output of Java with nested loops and conditionals, and reasoning about time and space complexity. Because the screen is timed, practise on a clock and by hand.

What to demonstrate

  • Logical and numerical reasoning on timed puzzles
  • Reading Java quickly and predicting what it prints
  • Basic complexity analysis with Big O notation

How to prepare

  • Hand-trace nested-loop and conditional snippets with a trace table, then run them to check your prediction.
  • Practise turning an O(N^2) pair-search into an O(N) pass with a HashSet or HashMap.
  • Review a few concurrency bugs you can spot by eye, such as an unsynchronized counter or a check-then-act race.
  • Run a set of number and deduction puzzles against a timer you set, and note which types cost you the most.

Technical and Panel Interviews

Candidates report that passing the assessment leads into technical interviews, including a panel with several interviewers. Candidates describe a deep dive into past project experience in the technical loop, and say some teams still ask for syntactically correct Java on a whiteboard or paper with no IDE. The reported Java and object-oriented questions (ConcurrentHashMap, garbage collection, polymorphism, reversing a linked list) are not tied to a specific round, so prepare them for any technical conversation.

What to demonstrate

  • Depth in core Java, memory management and collections
  • Object-oriented design applied to real project work
  • Syntactically accurate Java without an IDE, with edge cases handled
  • Explaining technical choices clearly to several people

How to prepare

  • Write the iterative linked-list reversal on paper with prev, curr and next, including the empty and single-node cases, then compile it to find your slips.
  • Be ready to explain ConcurrentHashMap and the generational heap in a few precise sentences each.
  • Choose one project and outline it: components, data store, integrations, failure points and what you would change.
  • Prepare a polymorphism example from your own work, including the interface or abstract class and what it replaced.

Practical Coding Challenge

Candidates describe building a small working service, such as a REST API, in the session; one reported scenario is a CRUD API for a clinical tracking system. A tip from candidates is to have the local environment ready beforehand, for example a Spring Boot setup, so setup does not consume the session. This is also the stage to practise the reported API questions on multi-step submissions, status codes, versioning and PHI security in code.

What to demonstrate

  • Working, compiling code rather than a description of it
  • API structure: resources, HTTP methods, request and response payloads
  • Persistence to a relational database with sensible SQL
  • Consistent error handling and correct HTTP status codes

How to prepare

  • Keep a Spring Boot skeleton you can generate in minutes: controller, service, repository, entity, DTO and a database connection.
  • Build a clinical-tracking CRUD API end to end several times, adding bean validation and a global exception handler that maps errors to status codes.
  • Practise a submission that arrives in several steps and must be safe to retry.
  • Write down your PHI answer: authentication, authorization, transport encryption, audit logging and keeping PHI out of logs and URLs.

Senior Manager Conversation

Candidates describe a closing conversation with a senior manager that covers fit, values and where you want your career to go. It is a conversation, not a coding stage, so the preparation is your own story: why this kind of work, what you have shipped, how you collaborate with clinical, product and QA colleagues, and where you want to grow. Candidates also advise being ready to discuss how you approach refactoring older code safely.

What to demonstrate

  • How you describe your career direction and motivation
  • Communication with non-engineering stakeholders
  • Fit with the team as discussed in the conversation

How to prepare

  • Rehearse concise versions of your legacy-code, disagreement and production-incident stories.
  • Prepare a clear answer on why healthcare technology and what you want your next two years to look like.
  • Write questions for the manager about the team, its mix of older systems and newer microservices, and how work is planned.

Where candidates lose points

Handwritten Java falls apart: a linked-list reversal that loses the next pointer, forgets the empty list, or misses semicolons and generics

Write the reversal on paper with prev, curr and next, trace a three-node list by hand, then type it in to compare. Repeat for the thread-safe singleton and a small class hierarchy until raw syntax stops costing you.

Calling ConcurrentHashMap 'a synchronized HashMap', or describing garbage collection as 'it frees unused objects'

State specifics: ConcurrentHashMap uses CAS and per-bin locking, rejects null keys and values, has weakly consistent iterators, and needs merge or computeIfAbsent for atomic compound updates. For GC, describe the heap generations, minor versus major collections, and one tuning lever with its trade-off.

Using the practical coding session to set up a project, or putting all logic in a single controller

Keep a tested Spring Boot skeleton and database connection ready. Get one vertical slice working first (controller, service, repository), then add validation and a global exception handler.

Sloppy HTTP semantics, such as 200 with an error body, 500 for bad input, or mixing up 401 and 403

Memorize the mapping: 400 for malformed requests, and one consistent choice of 400 or 422 for well-formed input that breaks a business rule; 401 for missing or failed authentication, 403 for an authenticated caller who lacks permission, 404 and 409 for missing resources and conflicts, and 500 only for unexpected failures with no stack trace in the response.

Answering the PHI question with 'use HTTPS' and nothing more

Layer the answer: transport encryption, authentication and role-based authorization, least-privilege data in responses, audit logging of access, encryption at rest, and PHI kept out of URLs, logs and error messages.

Questions & practice

Explain the difference between a HashMap and a ConcurrentHashMap in Java, and when you would use each.

Medium · Java & Object-Oriented Programming

Approach

  1. HashMap is not thread-safe: concurrent puts can lose updates or corrupt the table during a resize, and its iterators are fail-fast (best-effort ConcurrentModificationException). It allows one null key and null values.
  2. ConcurrentHashMap (Java 8+) has lock-free reads and writes that use CAS on an empty bin or lock only that bin's head node, so threads touching different bins do not block each other. Java 7 split the table into segments instead.
  3. ConcurrentHashMap rejects null keys and values, because get() returning null must mean absent. Its iterators are weakly consistent and never throw ConcurrentModificationException, and size() is only an estimate while updates are in flight.
  4. Thread safety per call does not make a get-then-put sequence atomic. For compound updates I use merge(key, 1L, Long::sum), computeIfAbsent or putIfAbsent, and I keep the mapping function short because it runs while the bin is locked.
  5. When to use each: HashMap for data confined to one thread or built once and then safely published read-only. ConcurrentHashMap for shared mutable state such as caches or per-key counters. Collections.synchronizedMap uses one lock for everything, and you must lock it by hand while iterating.

Follow-up

  • Why does ConcurrentHashMap refuse null keys and values when HashMap accepts them?
  • How would you keep a thread-safe hit counter per key, and why is get() followed by put() wrong?
  • What can go wrong if several threads write to a plain HashMap while it resizes?

How does garbage collection work in the JVM, and what are the common strategies to optimize memory management?

Medium · Java & Object-Oriented Programming

Approach

  1. The JVM decides what is garbage by reachability from GC roots (thread stacks, static fields, JNI references), not by reference counting, so unreachable cycles are collected. Class metadata lives in Metaspace (native memory since Java 8), not on the heap.
  2. The generational heap: new objects go into Eden. A minor GC copies the survivors into a survivor space, and objects that outlive the tenuring threshold are promoted to the old generation, which major or full collections mark, sweep and compact.
  3. Collectors trade throughput for pause time. Serial suits small heaps, Parallel maximises throughput, G1 (default since JDK 9) uses regions and a pause-time goal, and ZGC and Shenandoah do most of their work concurrently to keep pauses short. CMS was removed in JDK 14.
  4. Measure before tuning: turn on GC logging (-Xlog:gc* on JDK 9+), look at pause times and allocation rate with JFR or jstat, then size the heap with -Xms and -Xmx and pick a collector that matches the latency target.
  5. Most real gains come from the code: cut allocation in hot paths (boxing, temporary strings, StringBuilder in loops) and fix leaks such as unbounded static caches, unremoved listeners and ThreadLocals in pooled threads. Find them with a heap dump (-XX:+HeapDumpOnOutOfMemoryError) and a dominator-tree tool like Eclipse MAT.

Follow-up

  • How would you find a memory leak in a running Java service without restarting it?
  • What is the difference between 'OutOfMemoryError: Java heap space' and 'OutOfMemoryError: Metaspace'?
  • When would you use a WeakReference or SoftReference, and what does System.gc() actually guarantee?

Write a syntactically correct method to reverse a singly linked list using pen and paper.

Medium · Java & Object-Oriented Programming

Approach

  1. Write the node class and signature first so the syntax is complete: class ListNode { int val; ListNode next; } and public ListNode reverse(ListNode head).
  2. Iterative three-pointer reversal: ListNode prev = null, curr = head; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev;. That is O(n) time and O(1) extra space.
  3. The ordering rule that prevents losing the list: save curr.next before overwriting it. Then check the result by tracing 1->2->3 on paper and writing out prev, curr and next for each iteration.
  4. Edge cases to state and check: an empty list (head == null returns null), a single node, and two nodes. The new head is prev, not curr, which is null when the loop ends.
  5. Recursive alternative, written in full: if (head == null || head.next == null) return head; ListNode newHead = reverse(head.next); head.next.next = head; head.next = null; return newHead;. Without the base case it fails with a NullPointerException on paper. It uses O(n) stack, and Java does no tail-call elimination, so a very long list can throw StackOverflowError. That is why I lead with the iterative version.

Follow-up

  • Reverse only the nodes between positions m and n in one pass.
  • Reverse the list in groups of k nodes, leaving a short final group as it is.
  • How does the code change for a doubly linked list?

How do you analyze the time and space complexity of an algorithm using Big O notation?

Medium · Aptitude & Logical Reasoning

Approach

  1. Choose the input size variables and count the dominant operation as a function of them, dropping constants and lower-order terms. Keep separate variables for separate inputs: O(n + m) or O(n x m), not O(n^2).
  2. Loop patterns: sequential loops add and nested loops multiply. An inner loop that starts at the outer index is still O(n^2) (n(n+1)/2 iterations). A loop that halves or doubles its variable is O(log n), so an O(n) loop around it gives O(n log n).
  3. Recursion: write the recurrence. T(n) = 2T(n/2) + O(n) gives O(n log n) (merge sort, by the master theorem). Naive Fibonacci is exponential (bounded by O(2^n)), and memoization brings it to O(n).
  4. Space means auxiliary memory: new collections plus recursion depth (O(n) for linear recursion, O(log n) for recursive binary search). Distinguish best, average, worst and amortized cases; ArrayList.add is amortized O(1) and quicksort's worst case is O(n^2).
  5. Watch for hidden costs: ArrayList.contains inside a loop is O(n) per call, while a HashSet lookup averages O(1). That is the usual way to cut a nested O(n^2) pair search to O(n). String += in a loop copies the string each time, so use StringBuilder.

Follow-up

  • Turn an O(n^2) search for a pair that sums to a target into an O(n) solution, and state its space cost.
  • What is the complexity of for (i = 1; i < n; i *= 2) { for (j = 0; j < i; j++) {...} }? (O(n): 1 + 2 + 4 + ... < 2n.)
  • Why is appending to an ArrayList O(1) amortized when a resize copies every element?

Explain why the owner filter ignores the listing index

Medium · composite index · query plans · sort elimination

The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.

Approach

  1. Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
  2. For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
  3. Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
  4. Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.

Follow-up

  • 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
  • A dashboard runs this for 40 owners in one page load. What changes about the design?

Hold a per-tenant active cap against concurrent creates

Hard · write skew · isolation levels · constraints

A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.

Approach

  1. Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
  2. Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
  3. Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
  4. State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.

Follow-up

  • A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
  • The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?

Describe the principles of Object-Oriented Programming (OOP) and give a real-world example of how you applied

Medium · Java & Object-Oriented Programming

Describe the principles of Object-Oriented Programming (OOP) and give a real-world example of how you applied polymorphism in a past project.

Approach

  1. Define the four principles precisely. Encapsulation: private state whose invariants only the class's methods can change. Abstraction: callers depend on an interface, not an implementation. Inheritance: is-a reuse of behaviour. Polymorphism: one call site, with the behaviour chosen by the object's runtime type.
  2. Separate the two kinds of polymorphism. Overloading is resolved at compile time from the static argument types. Overriding is resolved at runtime by dynamic dispatch. Only overriding removes type switches from the calling code.
  3. Give the example a clear shape: the type switch or if-chain that existed before, the interface I introduced, two or three implementations, how the right one was chosen (factory, configuration or dependency injection), and what adding a new type cost afterwards.
  4. Tie the example to design principles. It is open/closed (a new type is a new class, not an edited switch) and it must obey Liskov substitution (each implementation honours the interface's contract, with no surprise exceptions or stronger preconditions).
  5. Name the trade-off. Deep inheritance trees are fragile, so I prefer composition and strategy-style interfaces when behaviour varies independently, and I use an abstract base class only for shared state or template steps.

Follow-up

  • When does subclassing violate Liskov substitution? Give a concrete example.
  • Abstract class or interface in Java 8+, now that interfaces can have default methods: how do you choose?
  • If two overloaded methods both match a call, which one does Java pick, and when is that decided?

How do you design a RESTful API endpoint to handle complex, multi-step clinical data submissions?

Medium · RESTful API Development

Approach

  1. Model the submission as a resource with a lifecycle. POST /submissions creates it in an OPEN state and returns 201 with a Location header. PUT or PATCH /submissions/{id}/steps/{step} saves each step. POST /submissions/{id}/submit moves it to SUBMITTED once the server confirms every required step is present.
  2. Validate at two levels. Each step checks its own fields and returns 400 or 422 with field-level errors. The final submit checks cross-step rules, and it returns 409 Conflict for an invalid transition such as submitting twice or editing after submission.
  3. Make retries safe. PUT is idempotent by definition. For the POSTs, accept an Idempotency-Key header and store it with the result, so a client retrying after a timeout gets the original response instead of a duplicate submission.
  4. Protect against concurrent edits with optimistic locking: return an ETag (or a version field backed by JPA @Version), require If-Match on updates, and answer 412 Precondition Failed when the version is stale.
  5. If downstream review is slow, return 202 Accepted from submit with a status URL the client can poll or a callback. Keep an append-only audit trail of state changes, and keep clinical payloads out of logs.

Follow-up

  • What happens to submissions a client abandons halfway, and how do you expire or clean them up?
  • How would you accept a large document attachment as one of the steps?
  • How do you change the schema of one step without breaking clients that are halfway through a submission?

What HTTP status codes are most appropriate for handling authentication failures, validation errors, and inter

Medium · RESTful API Development

What HTTP status codes are most appropriate for handling authentication failures, validation errors, and internal server exceptions?

Approach

  1. Authentication versus authorisation: 401 Unauthorized when credentials are missing, invalid or expired (the spec says to send a WWW-Authenticate header), and 403 Forbidden when the caller is authenticated but not allowed. Some APIs return 404 instead of 403 so they do not reveal that a record exists.
  2. Validation: 400 Bad Request for a malformed request such as unparseable JSON or a wrong type, and 422 Unprocessable Content (RFC 9110's name) for well-formed input that breaks business rules. Pick one convention and use it everywhere. 415 covers the wrong Content-Type and 409 a conflict with the current state.
  3. Server side: 500 for an unhandled exception, with a generic message and no stack trace in the body. 502 or 504 when an upstream dependency fails or times out, and 503 with Retry-After when the service is overloaded or in maintenance.
  4. Return one error shape for all of them, for example RFC 9457 Problem Details (application/problem+json; Spring 6 has a ProblemDetail class) built in a single @RestControllerAdvice, with a correlation ID the client can quote to support.
  5. Remember the retry semantics: clients should not retry most 4xx responses unchanged, but they can retry 503 and 504 with backoff, so the code you choose changes client behaviour.

Follow-up

  • A request arrives with an expired token. Is that 401 or 403, and what should the body say?
  • What status do you return for rate limiting, and which header goes with it?
  • Should a DELETE on a resource that no longer exists return 404 or 204?

Walk through the process of building a REST API from scratch using Spring Boot or a similar framework.

Medium · RESTful API Development

Approach

  1. Bootstrap with Spring Initializr: spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-validation and a database driver (H2 for speed, or Postgres if a real database is required). Get one endpoint working end to end before adding more.
  2. Layer the code: @RestController for HTTP only, @Service for business rules and @Transactional boundaries, a JpaRepository interface for persistence, and an @Entity. Request and response DTOs stay separate from entities so the API contract does not leak the schema.
  3. CRUD semantics: GET /items (paged with Pageable), GET /items/{id} (404 if missing), POST returning 201 with ResponseEntity.created(uri), PUT or PATCH for updates, and DELETE returning 204. Put @Valid on the @RequestBody, with constraints such as @NotNull and @Size on the DTO.
  4. Central error handling: a @RestControllerAdvice maps a not-found exception to 404 and MethodArgumentNotValidException to 400 with field errors, so every controller returns the same error shape.
  5. Prove it works: @WebMvcTest with MockMvc for the controller, @DataJpaTest for repository queries, plus a curl call per endpoint. Mention the next steps: Spring Security, @Version for concurrent updates, and fetch joins to avoid N+1 queries.

Follow-up

  • How would you add authentication and per-endpoint authorisation to this API?
  • Two clients update the same record at once. How does your API detect and report that?
  • A list endpoint is slow, and the SQL log shows one query per row. What is happening and how do you fix it?

Explain how you would secure an API endpoint that handles protected health information (PHI).

Medium · RESTful API Development

Approach

  1. Transport: TLS 1.2 or later on every hop, internal service-to-service calls included (mTLS between services). Never put PHI in URLs or query strings, because they end up in access logs, proxies and browser history.
  2. Authentication: OAuth 2.0 or OpenID Connect with short-lived access tokens, validated on every request for signature, issuer, audience and expiry, rather than long-lived API keys.
  3. Authorisation at two levels: a scope or role check for the endpoint, and an object-level check that this caller may see this particular patient's record. Missing object checks are Broken Object Level Authorization, the first item in the OWASP API Security Top 10.
  4. Data handling: return only the fields the caller needs, encrypt at rest with managed keys, set Cache-Control: no-store on responses, and redact PHI from application logs and error messages. Validate input and use parameterized queries.
  5. Accountability: write an audit record of who accessed which record and when (HIPAA's Security Rule includes audit controls), and add rate limiting and alerts on unusual access patterns, such as one account reading thousands of records.

Follow-up

  • JWTs are stateless. How do you revoke access for a compromised account before its token expires?
  • How do engineers debug production issues when the logs must not contain PHI?
  • How would you secure a bulk export endpoint that returns many patients' records?

Solve a series of numerical and logical deduction puzzles within a 15-minute timeframe.

Medium · Aptitude & Logical Reasoning

Approach

  1. Triage the whole set first: answer the quick items, mark any item that needs more than a few steps, and come back to it. Read the instructions to see whether wrong answers cost marks before deciding to guess.
  2. Number series: check the differences, then the second differences, then ratios, then two interleaved sequences, then squares, cubes and primes. Example: 2, 6, 12, 20, 30 has differences 4, 6, 8, 10, so the next term is 42.
  3. Arithmetic shortcuts: work rates add as 1/t1 + 1/t2; successive percentage changes multiply, so +20% then -20% is 1.2 x 0.8 = 0.96, a 4% loss; averages are easier through totals (average x count).
  4. Logical deduction: draw syllogisms as Venn diagrams, and for ordering or seating puzzles build a grid and place the most constrained item first. When a direct solve is slow, plug each answer option back into the constraints and eliminate.
  5. Estimate before computing: rounding often rules out three of four options, which saves time for the harder items.

Follow-up

  • Pipe A fills a tank in 6 hours and pipe B in 3 hours. How long do they take together? (2 hours, since 1/6 + 1/3 = 1/2.)
  • All A are B and some B are C. Does it follow that some A are C? (No: the B that are C may not include any A.)
  • A price rises 25% and then falls 20%. What is the net change? (None: 1.25 x 0.8 = 1.)

Predict the output of a specific Java code segment containing nested loops and conditional statements.

Medium · Aptitude & Logical Reasoning

Approach

  1. Keep a trace table on paper, with one column per loop variable and accumulator and one row per iteration, instead of simulating in your head. Count the iterations first: if the outer loop runs i from 0 to n-1 and the inner loop starts at j = i, the body runs n(n+1)/2 times.
  2. Check the boundaries: < against <=, whether the inner loop starts at 0, i or i+1, and whether a variable is changed inside the loop body as well as in the header.
  3. Control flow: an unlabelled break or continue affects only the innermost loop; a labelled break leaves the named loop. An if without braces controls only the next statement, and a dangling else belongs to the nearest if.
  4. Java specifics: integer division truncates toward zero (-7 / 2 is -3, -7 % 2 is -1); i++ yields the old value and ++i the new one, so x = x++ leaves x unchanged; && and || short-circuit but & and | do not; int arithmetic overflows silently.
  5. Output format: "" + 1 + 2 prints 12 but 1 + 2 + "" prints 3, because evaluation runs left to right. print and println differ by the newline, so write the exact characters, spaces and line breaks.

Follow-up

  • How does the output change if the break in the inner loop becomes a continue?
  • What is printed by int x = 5; x = x++ + ++x; System.out.println(x);? (12: 5 + 7.)
  • Rewrite the loop so the inner break leaves both loops.

Walk me through the architecture of the most complex software system you have designed and deployed.

Medium · Behavioral & Project Experience

Approach

  1. Open with one sentence on what the system did and who used it, then give the scale figures you actually know (requests, records, users), clearly labelled as your own measurements.
  2. Draw the boxes in order: clients, entry point (load balancer or gateway), services, data stores, queues or batch jobs, and external integrations. Then walk one write request and one read request end to end through them.
  3. Pick two or three decisions and give the alternative you rejected for each: for example a relational database for transactional integrity rather than a document store, or a queue to keep a slow integration off the request path. Say what each choice cost.
  4. Make your own part explicit in the first person: what you designed, what you inherited, and what you deployed and operated, including how it shipped (CI/CD, containers) and how you monitored it.
  5. Close with one production failure or bottleneck, how you found and fixed it, and what you would redesign today. That shows you ran the system, not just diagrammed it.

Follow-up

  • What breaks first if traffic grows ten times?
  • What happens to in-flight requests when your main database or a key integration is down?
  • Which design decision would you reverse today, and what would the migration look like?

Tell me about a time you had to debug a critical production issue under tight time constraints.

Medium · Behavioral & Project Experience

Approach

  1. Set the stakes in two sentences: what was failing, who was affected and how you found out (alert, error-rate graph, user reports). Then make clear you were the one doing the investigating.
  2. Mitigate before the root cause: roll back the recent deploy, turn off the feature flag, fail over or scale out. Say how you weighed rollback risk against waiting, and who you kept informed.
  3. Give the debugging sequence: what changed and when (deploys, config, traffic, dependencies), correlated against metrics, logs and traces; then narrow it down by bisecting. For a Java service, use thread dumps for hangs, heap dumps and GC logs for memory, and connection-pool metrics for timeouts.
  4. Separate the trigger from the cause, for example a traffic spike that exposed an unbounded query or a missing timeout. Confirm the fix by watching the metric return to baseline, not by the absence of complaints.
  5. End with the follow-through: a regression test, a new alert or dashboard, a runbook entry or a blameless postmortem. Avoid a story where you only watched, or one with no numbers for impact and recovery.

Follow-up

  • How did you know your fix caused the recovery and not a coincidence?
  • What would you have done differently in the first ten minutes?
  • What did you change so the same failure would be caught earlier next time?

Suggested practice checklist

The plan follows the four reported rounds: Java depth and timed aptitude first, then a repeatable REST API build with security and versioning, then project stories for the panel and the manager conversation. Each day ends with something you produced.

Day 1 — Map the loop and ready your environment

  • Write out the four reported rounds and mark which one you are least ready for.
  • Generate a Spring Boot project that builds, starts and connects to a local relational database.
  • Go down this checklist: stack vs heap, GC generations, HashMap and ConcurrentHashMap internals, volatile and synchronized, checked vs unchecked exceptions, and the thread-safe singleton. Mark every item you cannot explain aloud in 60 seconds.

Deliverable: A one-page round map with the weakest round marked, a Spring Boot skeleton that runs, and a marked Java checklist.

Day 2 — Collections, concurrency and the JVM

  • Write a short, precise explanation of HashMap versus ConcurrentHashMap, covering locking, nulls, iterators and compound operations.
  • Outline how garbage collection works: generations, minor and major collections, one tuning lever, and how you would diagnose a memory leak.
  • Write a thread-safe singleton by hand two ways, such as the holder idiom and an enum.

Deliverable: Two written explanations and two handwritten singleton implementations.

Day 3 — Pen-and-paper Java and object-oriented design

  • Reverse a singly linked list on paper, iteratively and recursively, then compile your versions to find slips.
  • Write out the four OOP principles with an example of polymorphism from your own work.
  • Write one example showing checked versus unchecked exceptions, including a @Transactional rollback case.

Deliverable: Handwritten reversal code, a polymorphism example and an exception example, each checked against a compiler.

Day 4 — Timed aptitude and complexity

  • Run a set of number and logic deduction puzzles against a timer you set and review every miss.
  • Hand-trace five Java snippets with nested loops and conditionals before running them.
  • Take three O(N^2) loops and rewrite each to O(N) with a hash-based structure, stating the space cost.

Deliverable: A scored puzzle log, five trace tables and three before-and-after complexity rewrites.

Day 5 — Build a clinical-tracking REST API

  • Build CRUD endpoints for a clinical tracking resource with controller, service, repository and DTOs.
  • Add bean validation and a @ControllerAdvice handler returning consistent errors and correct status codes.
  • Add a multi-step submission flow with an idempotency key so a retry cannot be applied twice.

Deliverable: A working API with tests covering success, validation failure, not found and a retried submission.

Day 6 — PHI security, versioning and the database layer

  • Add authentication and role-based authorization to the API, and write down audit logging and what must stay out of logs and URLs.
  • Add a /v2 route with a changed payload while keeping /v1 working, and write the deprecation steps.
  • Tie SQL, transactions and persistence to the clinical-tracking API: write the paged list query, add an index for its filter, and set @Transactional boundaries for the multi-step submit.

Deliverable: A secured API serving two versions, a written PHI checklist, an indexed paged query with transactional submit, and notes from the SQL practice questions.

Day 7 — Project stories and the manager conversation

  • Outline the architecture story for your most complex system: components, data flow, failure points and what you would change.
  • Write structured outlines for the legacy-code, disagreement and production-debugging stories, each with a measured result.
  • Rehearse your career-goals answer and a short list of questions for the senior manager.

Deliverable: Four story outlines, a career-goals answer and a list of manager questions, rehearsed out loud.

Project, legacy-code and disagreement stories

The reported project questions ask about the largest system you have built, working with legacy code, disagreeing with product managers or senior leaders, and debugging a production issue. Candidates also describe a senior manager conversation about team fit and career goals. Prepare stories where you made the decision, name the risk and show a result, and keep one eye on how you explain technical choices to clinical and business colleagues.

  1. Walk me through the architecture of the most complex software system you have designed and deployed.
  2. Tell me about a time you had to debug a critical production issue under tight time constraints.
  3. Describe the principles of Object-Oriented Programming (OOP) and give a real-world example of how you applied polymorphism in a past project.

What is the difference between checked and unchecked exceptions in Java, and how do you handle them effectivel

Medium · Java & Object-Oriented Programming

What is the difference between checked and unchecked exceptions in Java, and how do you handle them effectively?

Approach

  1. Define it precisely: a checked exception is Exception or a subclass that is not a RuntimeException, so the compiler forces every caller to catch it or declare it with throws. Unchecked exceptions are RuntimeException and its subclasses, plus Error, and the compiler imposes nothing.
  2. Give the design rule: use checked exceptions for conditions a caller can reasonably recover from, such as a missing file or a remote call worth retrying, and unchecked ones for programming errors and broken preconditions such as NullPointerException, IllegalArgumentException and IllegalStateException. Spring wraps persistence failures in unchecked exceptions so service code is not full of throws clauses.
  3. Handling: catch only where you can act, wrap with the original cause (new OrderException(message, e)) so the stack trace survives, never leave an empty catch block, never catch Throwable, use try-with-resources for closeable resources, and log once at the boundary instead of at every layer.
  4. Name the traps: @Transactional rolls back on unchecked exceptions and Errors by default but not on checked ones unless rollbackFor is set; checked exceptions cannot cross standard functional interfaces in stream lambdas without wrapping; a return inside finally silently discards an in-flight exception.
  5. This question is filed under behavioral, so close with a one-sentence real case, such as an exception you stopped swallowing or a transaction that did not roll back, and the fix. In a REST service, finish with a @ControllerAdvice handler that maps exception types to status codes.

Follow-up

  • Why might a service method that throws a checked exception still commit its transaction?
  • How would you call a method that throws IOException inside a stream map without hiding the failure?
  • If the try block throws and close() also throws in a try-with-resources, which exception does the caller see?

How do you handle versioning in RESTful APIs to ensure backward compatibility for external clients?

Medium · RESTful API Development

Approach

  1. Start with what counts as breaking: removing or renaming a field, changing a type, tightening validation, or changing a status code or the meaning of a value. Adding an optional field or a new endpoint is compatible as long as clients ignore unknown fields, so most changes should not need a new version.
  2. Compare mechanisms and pick one: a URI path such as /api/v1/submissions is visible and easy to route and test; media-type or custom-header versioning keeps URLs stable but is harder to try by hand; a query parameter is simple but easy to omit. In Spring this is usually a controller class per version over one service layer.
  3. Keep request and response DTOs separate from entities and map per version, so a database change cannot alter the public contract. For a column rename use expand then contract: add the new column, write to both, move readers over, then drop the old one.
  4. Cover the lifecycle: run both versions in parallel, announce deprecation with Deprecation and Sunset headers plus direct contact, log version and caller on every request, and retire a version only when its traffic is gone. Catch accidental breaks in CI with an OpenAPI diff or consumer contract tests.
  5. This question is filed under behavioral, so ground it in one change external consumers could not redeploy quickly: the option you rejected, what you measured (calls per version) and what you would do differently.

Follow-up

  • A client says they cannot leave v1 before the sunset date. What do you do?
  • How would you catch an accidental breaking change before it reaches production?
  • When would you choose header-based versioning over a URI path?

Describe a time when you had to work with legacy code. How did you approach understanding and modifying it?

Medium · Behavioral & Project Experience

Approach

  1. Choose a story where you changed code you did not write, with weak tests or little documentation. State in two sentences what the system did and what change was needed, then spend the rest on method.
  2. Show how you learned it before editing: you ran it locally, traced one real request from entry point to database, read the commit history and tickets behind the confusing parts, and asked people who had worked on it.
  3. Show how you made the change safe: characterization tests that pin current behavior (odd behavior included) before touching anything, small refactors behind that safety net, a feature flag or parallel run for risky paths, and small reviewable pull requests.
  4. Give the result with evidence: defects after release, tests added, how much faster the next change in that area was. Mention one surprise, such as an undocumented consumer of the code.
  5. The story fails if it is 'I rewrote it' with no way to show behavior was preserved, or if it blames the previous authors. Be ready to explain why you refactored rather than rewrote.

Follow-up

  • There were no tests and nobody who understood the code. Where did you start?
  • How did you confirm production behavior was unchanged after release?
  • When would you have recommended a rewrite instead?

How do you handle disagreements with product managers or senior leaders regarding technical implementation det

Medium · Behavioral & Project Experience

How do you handle disagreements with product managers or senior leaders regarding technical implementation details?

Approach

  1. Pick a disagreement about a concrete technical detail, such as a schema shape, a build-versus-buy choice, a deadline that skipped testing or an API contract, not a personality clash. Name the other person's role and what they were trying to achieve.
  2. Show that you first understood their goal and constraint, such as a date, a customer commitment or a compliance need, and said it back to them before arguing your side.
  3. Bring evidence instead of opinion: a prototype, a benchmark, defect or incident history, or an estimate of rework cost. Translate the technical risk into their terms: delay, cost or exposure of sensitive data.
  4. Offer options with trade-offs, for example ship the narrow version now and schedule the hardening, or put it behind a flag. If you were overruled, describe how you disagreed, committed and recorded the risk.
  5. End with the outcome and the working relationship afterwards. The story sinks when you win by escalating over their head, or when the disagreement cost you nothing and shows no judgment.

Follow-up

  • What if you were overruled and it later went wrong?
  • The more senior person insists and you still believe the approach is unsafe. What do you do?
  • What evidence changed their mind, or yours?