cswork / libraryOpen practice workspace

Interview guides · Appex Innovations

Appex Innovations Software Engineer Interview Guide

Appex Innovations Software Engineer interview guide: four reported rounds, Java, Spring Boot, REST API, SQL and IAM questions, plus a 7-day prep plan.

The 60-second brief

Appex Innovations builds software for clients. Candidates describe the work as backend-heavy application development, with healthcare management portals and enterprise support systems named as example projects. The Software Engineer role reported here covers designing database schemas, building RESTful APIs, debugging, code reviews and tuning, and owning delivery of individual modules from requirements to release. The requirements candidates describe list Core Java, Spring Boot, REST APIs and SQL as must-haves, with Git and Maven for day-to-day work. Hibernate/JPA, Spring Security, Agile/Scrum and familiarity with IAM appear as extras. In practice that means a Java web-services engineer who can reason about data, security and project structure.

This guide is for candidates interviewing for a Software Engineer position at Appex Innovations, most directly those with Java and Spring Boot backgrounds. It covers the four reported rounds, all twelve reported questions (string and number programs, collections and concurrency, Spring Boot and REST design, SQL, indexing, access control and an object-oriented design exercise), the behavioral themes candidates describe, and a seven-day plan.

Candidates report four rounds spread over about three to five weeks: Initial Screening, Technical Assessment, Managerial Discussion and Final Round. Some candidates report that the final round is an in-person office visit.

Focus areas

  • Java
  • REST API Design
  • Spring Boot

Overview

The reported questions fall into three groups. The first is small Core Java programs and library knowledge: reversing a string and checking a palindrome, listing primes in a user-supplied range, validating balanced parentheses, and comparing HashMap with ConcurrentHashMap. The second is Spring-style backend design: a member registration REST module, the roles of annotations, beans and controllers, web services versus APIs, and the architecture of a project from your own resume. The third is data and security: WHERE versus HAVING, indexing for query performance, RBAC and IAM, and an object-oriented healthcare management portal.

Because the programs are short, the preparation is about completeness rather than cleverness. For each one, decide the contract first (what is the input, what is returned, what happens for null, empty or inverted input), then write clean Java, then walk through a table of test cases. Candidates are also advised to think aloud while coding, so rehearse narrating your choices while you type, not only producing the final code.

The stack that candidates list for the role is Core Java, Spring Boot, REST, SQL, Git and Maven, with Hibernate/JPA, Spring Security and Agile as extras. Be ready to say why you chose a framework or pattern over an alternative, and to describe the full path of a request from controller to service to repository to database, including where authentication and authorization happen.

Candidates also report that anything on your resume is open to questioning, and that scenario questions about tight deadlines, client expectations, AI-assisted development and continuous learning come up. Prepare two project architecture walkthroughs and two or three scenario stories before you start drilling code.

The Appex Innovations interview process

Candidates report four rounds over about three to five weeks: Initial Screening, Technical Assessment, Managerial Discussion and Final Round. The reported questions are grouped by topic below, not assigned to individual rounds.

Initial Screening

Candidates describe the Initial Screening as a first check of your qualifications. Because candidates are told that every technology and project on a resume is open to later questions, treat this stage as the point where your resume story has to be coherent and honest. Prepare a short account of each project and each tool you list, and decide in advance what you will say about tools you only touched briefly.

What to demonstrate

  • How well your listed experience matches the Java, Spring Boot, REST and SQL stack the role lists
  • Your ability to summarise projects you delivered, including your own part in them

How to prepare

  • Write a two-sentence summary for each resume project: what it did, what you personally built, and which stack pieces were involved
  • Re-read every technology on your resume and make sure you can explain its basic purpose, with one concrete example from your own use
  • For any tool you have not used in depth, prepare a sentence on how you would learn it or which familiar tool you would compare it to

Technical Assessment

The Technical Assessment is described as a high-level check of technical depth. Candidates list Java fluency, multithreading, exception handling, Collections, Java 8 features, memory management, Spring Boot, Hibernate/JPA and SQL optimization among the areas covered, and the reported Core Java programs are the natural practice material for a stage like this. Candidates also mention remote online assessments somewhere in the loop. Practise writing complete Java with edge cases handled, and talk through your reasoning as you go.

What to demonstrate

  • Working Java code that handles edge cases and reads cleanly
  • Understanding of collections, concurrency, exception handling and memory management
  • Working knowledge of SQL, indexing and the Spring Boot and Hibernate/JPA layers

How to prepare

  • Write the string reversal and palindrome check, the primes-in-a-range program and the balanced-parentheses validator in plain Java, each with a table of test inputs
  • Prepare a precise answer on HashMap versus ConcurrentHashMap: thread safety, locking granularity, null handling and iterator behavior
  • Prepare WHERE versus HAVING with a short example, and an indexing answer that covers composite index column order and the cost of extra indexes

Managerial Discussion

The Managerial Discussion is a conversation with managerial staff, and candidates say it may include senior leadership. Candidates describe scenario-based questions about handling tight deadlines and client expectations, plus questions on how you use AI tools and keep learning. The listed responsibilities include owning delivery of modules and communicating status, so bring examples where you did exactly that.

What to demonstrate

  • Ownership of delivery, from translating requirements to reporting progress
  • How you respond to tight deadlines and shifting client expectations
  • Your view on AI-assisted development and continuous learning

How to prepare

  • Write three scenario stories in situation, action, result form: a deadline you met or renegotiated, a requirement that changed mid-project, and a mistake you owned and reported early
  • Prepare a concrete, honest answer on where AI tools fit into your workflow and where you still check their output by hand
  • Be ready to explain a design trade-off you made in a past project and what you would change now

Final Round

The Final Round is reported to be, in some cases, an in-person visit to the office. Confirm the format with the recruiter so that logistics do not cost you focus. Use the time before it to tighten the two things the whole loop leans on: a clear walk through the architecture of a project from your resume, and calm, specific answers about trade-offs.

What to demonstrate

  • Clear communication of design decisions and the trade-offs behind them
  • Depth on the technologies you claim, including API flows and authentication in your own projects
  • How you present yourself in person or on screen to a broader group of staff

How to prepare

  • Rehearse an architecture walkthrough of one resume project out loud: components, request path from controller to database, how callers authenticate, and what you would change
  • Be able to sketch that architecture on paper or a whiteboard without notes
  • Ask the recruiter whether the final round is remote or on site, and plan travel and materials accordingly

Where candidates lose points

Writing the string reversal or palindrome check for the happy path only, with no thought for null, empty input, mixed case, spaces and punctuation

State the contract before coding: whether case and non-letters count, what null returns. Use a two-pointer comparison, then run a written test table covering null, empty, one character, mixed case and a phrase with punctuation.

Checking every number in the prime range by dividing by all smaller values, and forgetting inputs like a start below 2 or a start greater than the end

Test divisors only up to the square root, or use a Sieve of Eratosthenes when the range is large. Handle start below 2, an inverted range and a non-numeric entry explicitly, and say the time complexity of your choice.

A balanced-parentheses validator that handles one bracket type, pops from an empty stack on a stray closer, or ignores openers left over at the end

Use a Deque as a stack, map each closer to its opener, return false on a mismatch or an empty stack, and return true only when the stack is empty after the last character. Test (), ([]){}, ([)], a lone ) and (( .

Describing the member registration API as a list of annotations without explaining the data model, validation, duplicate handling or password storage

Walk through entity, unique constraint on email, request DTO with validation, service layer and transaction, a repository, and status codes (201 on create, 400 on invalid input, 409 on a duplicate). Say the password is stored hashed, never in plain text.

Giving a vague tour of a resume project, unable to say how requests are authenticated, where authorization happens or why a framework was chosen

Before the loop, trace one request through your own project and write down every hop, the auth mechanism, the schema and one decision you would revisit. Drop any resume item you cannot discuss in this depth.

Questions & practice

Explain the architectural differences between a HashMap and a ConcurrentHashMap in a multithreaded environment

Medium · Core Java & Programming

Explain the architectural differences between a HashMap and a ConcurrentHashMap in a multithreaded environment.

Approach

  1. HashMap is an array of buckets holding linked nodes. A bin becomes a red-black tree once it reaches 8 nodes and the table has at least 64 buckets. It has no synchronization: concurrent puts can lose updates or leave the map inconsistent, and in Java 7 a concurrent resize could create a cycle that sent get() into an infinite loop.
  2. Since Java 8, ConcurrentHashMap has no Segment locks (Java 7 split the map into segments). It uses CAS to insert into an empty bin and synchronizes only on a bin's first node otherwise. get() takes no lock, and several threads share the work of a resize.
  3. Iterators: HashMap's are fail-fast (best effort) and throw ConcurrentModificationException. ConcurrentHashMap's are weakly consistent and never throw it. size() on a concurrent map is only an estimate while writers are active.
  4. ConcurrentHashMap rejects null keys and values, because a null from get() could not tell "absent" apart from "mapped to null". HashMap allows one null key and null values.
  5. A thread-safe map does not make a get-then-put sequence atomic. Use putIfAbsent, computeIfAbsent or merge, for example counts.merge(word, 1, Integer::sum). Compare with Collections.synchronizedMap and Hashtable, which lock the whole map on every call.

Follow-up

  • How would you write a thread-safe word counter, and why is get() followed by put() wrong even on a ConcurrentHashMap?
  • Why does ConcurrentHashMap forbid null keys and values?
  • When would Collections.synchronizedMap still be a reasonable choice?

Collapse a redelivered event batch into per-aggregate high-water marks

Easy · hashing · at-least-once · aggregation

You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.

Approach

  1. One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
  2. Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
  3. Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
  4. If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.

Follow-up

  • The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
  • How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?

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?

How do you approach database indexing to optimize query performance?

Medium · Database & System Design

Approach

  1. Start from the slow query, not the table. Run EXPLAIN, or EXPLAIN ANALYZE where it is safe, and look for full scans, rows examined far above rows returned, and explicit sort steps.
  2. B-tree indexes serve equality, ranges, ORDER BY and prefix matches. In a composite index, put equality columns first and the range or sort column last. Leftmost-prefix rule: an index on (a, b) helps WHERE a = ? AND b > ? and WHERE a = ?, but generally not WHERE b = ? alone.
  3. A covering index contains every column the query reads, so the table is never visited (an index-only scan; PostgreSQL has INCLUDE columns). In InnoDB the primary key is the clustered index, and every secondary index stores the primary key.
  4. Know what defeats an index: a function on the column (LOWER(email) = ? needs an expression index or a normalised column), a leading-wildcard LIKE '%x', implicit type conversion, and low-selectivity columns where a scan is cheaper.
  5. Indexes have a cost: each one slows INSERT, UPDATE and DELETE and takes storage. Index the foreign keys you join on, drop unused indexes, and with Hibernate read the generated SQL first. An N+1 query pattern is fixed with fetch joins, not indexes.

Follow-up

  • Which index would you create for WHERE status = ? AND created_at > ? ORDER BY created_at?
  • The optimizer ignores your new index. How do you find out why?
  • What is the difference between a clustered and a non-clustered index?

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?

Write a Java program to reverse a string and check if it is a palindrome, handling different edge test cases.

Medium · Core Java & Programming

Approach

  1. Reverse with new StringBuilder(s).reverse().toString(), or by swapping a char[] from both ends in O(n). StringBuilder.reverse keeps surrogate pairs (emoji) together; a naive char swap splits them.
  2. To check for a palindrome, skip building the reversed copy. Walk two indices inward from both ends and stop at the first mismatch: O(n) time, O(1) extra space.
  3. Agree the rules before coding: is the check case-insensitive, and should spaces and punctuation be ignored? For "A man, a plan, a canal: Panama", skip characters where Character.isLetterOrDigit is false and compare Character.toLowerCase values.
  4. Edge cases to state and test: null (throw or return false, and say which), empty string and a single character (both palindromes), even and odd lengths, "ab", and a string made only of punctuation.
  5. Keep the logic in a pure method like boolean isPalindrome(String s), separate from Scanner input, so you can run a quick table of cases out loud.

Follow-up

  • How would you check whether any permutation of the string could form a palindrome?
  • How would you find the longest palindromic substring, and at what complexity?
  • What changes if the input holds combining characters or emoji rather than plain ASCII?

Find and display all prime numbers within a specified user-input range.

Medium · Core Java & Programming

Approach

  1. Validate the input first. Catch InputMismatchException from Scanner, decide whether to swap or reject lo > hi, and note that nothing below 2 is prime, so negative bounds yield an empty result.
  2. Trial division: test divisors while i * i <= n (using long avoids overflow), handle 2 on its own, then try odd divisors only. That costs O((hi - lo) * sqrt(hi)), which is fine for small ranges.
  3. Sieve of Eratosthenes up to hi: a boolean[] or BitSet where, for each prime p, multiples are crossed off starting at p * p. It runs in O(hi log log hi) time and O(hi) memory, and wins when the range starts near zero.
  4. Segmented sieve when hi is large but the window is narrow: sieve the primes up to sqrt(hi), then mark their multiples in a boolean array of size hi - lo + 1, starting each prime at max(p * p, ceil(lo / p) * p).
  5. Return a List<Integer> (or long) from a pure method and print it separately. Test 0, 1, 2, a range with no primes such as [24, 28], and lo == hi.

Follow-up

  • What would you change for a range like [10^12, 10^12 + 10^6]?
  • How would you answer many count-only queries over different ranges quickly?
  • Why is it enough to test divisors up to the square root?

Develop a program to validate balanced expressions by checking if all opening and closing parentheses match co

Medium · Core Java & Programming

Develop a program to validate balanced expressions by checking if all opening and closing parentheses match correctly.

Approach

  1. Scan once with an ArrayDeque<Character> as the stack (it is preferred over the legacy synchronized Stack class). Push every opener. On a closer, fail if the stack is empty or the top is not the matching opener, then pop. At the end the stack must be empty. O(n) time and O(n) space.
  2. Map closers to openers with a Map<Character, Character> or a switch, so adding [] and {} needs no new branches.
  3. If the input only ever contains round brackets, a counter is enough and uses O(1) space: increment on '(', decrement on ')', fail if it goes negative, and require zero at the end. Say why the counter breaks with mixed types: "([)]" balances by count but is invalid.
  4. Edge cases: an empty string (balanced), ")(" (count is fine but order is wrong), "(((" (leftover openers), operands and operators such as "a*(b+c)" that you skip, and null input.
  5. For a clearer error message, return the index of the first mismatch or of the unmatched opener instead of a bare boolean.

Follow-up

  • What is the minimum number of insertions needed to balance a string?
  • How would you ignore brackets that appear inside quoted string literals?
  • How would you find the length of the longest valid parentheses substring?

Create a backend REST API structure for a member registration module, detailing the database design and annota

Medium · Backend Frameworks & Architecture

Create a backend REST API structure for a member registration module, detailing the database design and annotations used.

Approach

  1. Endpoints: POST /members returns 201 Created with a Location header. Add GET /members/{id}, PATCH /members/{id}, and GET /members with page and size parameters. Treat DELETE as a status change to DEACTIVATED rather than a hard delete. Errors: 400 for validation, 404 for an unknown id, 409 for a duplicate email.
  2. Layering and annotations: a @RestController with @RequestMapping("/members") and @PostMapping that takes @Valid @RequestBody MemberRequest. The DTO carries Bean Validation (@NotBlank, @Email, @Size). Next comes a @Service whose write methods are @Transactional, and a MemberRepository extends JpaRepository<Member, Long>.
  3. Entity and schema: @Entity and @Table(name = "members") with a unique constraint on email, plus @Id and @GeneratedValue(strategy = GenerationType.IDENTITY). Columns: id, email (unique, stored lowercased), password_hash, full_name, status, created_at, updated_at, with @Column(nullable = false) where it applies.
  4. Duplicates: checking existsByEmail and then inserting is a race between two requests, so let the unique constraint decide. Catch DataIntegrityViolationException and map it to 409 in a @RestControllerAdvice. The same advice turns MethodArgumentNotValidException into a 400 with field errors.
  5. Security: hash passwords with BCryptPasswordEncoder. Return a response DTO, never the entity, so the hash cannot leak. If verification is in scope, keep status PENDING until an email token is confirmed.

Follow-up

  • What happens if two requests register the same email at the same moment?
  • How would you add email verification and resending of the token?
  • How would you version this API once mobile clients depend on it?

Discuss the role of Spring Boot annotations, beans, and controllers in building modular applications.

Medium · Backend Frameworks & Architecture

Approach

  1. @SpringBootApplication combines @Configuration, @EnableAutoConfiguration and @ComponentScan. Scanning starts from that class's package, so where it sits decides which beans are found. Auto-configuration is conditional (@ConditionalOnClass, @ConditionalOnMissingBean), so a bean you define yourself replaces the default one.
  2. A bean is an object the IoC container creates and wires. The stereotypes are @Component, @Service and @Repository (which also translates persistence exceptions), and @RestController, which is @Controller plus @ResponseBody. Use @Bean methods in a @Configuration class for third-party types you cannot annotate.
  3. Prefer constructor injection: fields can be final, dependencies are explicit, and unit tests need no container. A class with a single constructor needs no @Autowired (since Spring 4.3). When several beans share a type, choose one with @Primary or @Qualifier.
  4. The default scope is singleton, so a singleton bean is shared by every request thread and must be stateless or thread-safe. Other scopes include prototype, request and session.
  5. For modularity, keep controllers thin (HTTP mapping and validation only). Business rules and @Transactional go in services, and data access in repositories, with packages organised by feature. @Transactional works through a proxy, so calling such a method from inside the same class skips the transaction.

Follow-up

  • What happens at startup when two beans of the same type exist and neither is marked @Primary?
  • Why does a @Transactional method called from inside the same class not start a transaction?
  • How would you resolve a circular dependency between two services?

What is the fundamental difference between web services and APIs?

Medium · Backend Frameworks & Architecture

Approach

  1. An API is any defined contract for how software components interact: a library such as the Java Collections API, an operating-system call, or a network endpoint. A web service is an API exposed over a network using web protocols, usually HTTP. Every web service is an API, but not every API is a web service.
  2. Contrast the two common web-service styles. SOAP is an XML-envelope protocol with a WSDL contract and WS-* standards such as WS-Security. REST is an architectural style: resources identified by URIs, standard HTTP methods, stateless requests, and representations usually in JSON.
  3. Tie each to Java: JAX-WS for SOAP services, and JAX-RS or a Spring @RestController for REST.
  4. Name the trade-offs. SOAP gives a strict, machine-readable contract and suits enterprise integrations that require it. REST is lighter and uses HTTP caching and status codes. GET, PUT and DELETE are idempotent, while POST is not.
  5. Finish with a concrete example from your own work, such as a REST endpoint you built and an internal library API it called, so the distinction is shown rather than recited.

Follow-up

  • Is REST a protocol? What makes an API RESTful rather than just HTTP plus JSON?
  • What is the difference between PUT, PATCH and POST with respect to idempotency?
  • When would you choose SOAP or gRPC over REST?

Explain the end-to-end architecture of a project from your resume, including API flows and authentication impl

Medium · Backend Frameworks & Architecture

Explain the end-to-end architecture of a project from your resume, including API flows and authentication implementation.

Approach

  1. Open with one sentence on what the system did and who used it. Then sketch only the components that really existed: client, any load balancer or gateway, the Spring Boot services, the database, caches, queues and external APIs.
  2. Trace one real request end to end, for example creating an order: HTTP call, security filter chain, controller, validation, service and transaction boundary, repository, SQL, response. Then walk the error path that request takes when the database rejects it.
  3. Explain authentication exactly as it was built. With sessions: login, a server-side session and the cookie flags. With JWT: credentials checked against a bcrypt hash, a signed token with a short expiry, a refresh token, and a OncePerRequestFilter that validates the token and fills the SecurityContext. Authorization comes from roles checked via @PreAuthorize or URL rules.
  4. State the decisions and trade-offs in the first person: why I picked that database, why JWT over sessions (and that revoking a stateless token needs a denylist or short expiry), and what I would change now.
  5. Prepare to go one level deeper on every technology on your resume. Write the diagram and the request trace down before the interview so the explanation holds together under detailed questions.

Follow-up

  • How would you revoke a JWT before it expires?
  • Where is the token stored on the client, and what are the XSS and CSRF trade-offs of that choice?
  • Which component fails first if traffic grows ten times, and what would you change?

Explain the differences between WHERE and HAVING clauses.

Medium · Database & System Design

Approach

  1. WHERE filters individual rows before grouping. HAVING filters groups after GROUP BY has formed them and the aggregates are computed. Give the logical order: FROM/JOIN, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT.
  2. Aggregates cannot appear in WHERE (that is an error) but can in HAVING. Example: SELECT dept_id, COUNT() FROM employees WHERE status = 'ACTIVE' GROUP BY dept_id HAVING COUNT() > 10.
  3. Put conditions on plain columns in WHERE. That shrinks the rows to be grouped and lets an index help. Many optimizers push such predicates down from HAVING anyway, but writing them in WHERE does not depend on that.
  4. Edge cases: HAVING without GROUP BY treats the whole result as one group. MySQL accepts a SELECT alias in HAVING but PostgreSQL does not, so portable SQL repeats the aggregate. Also, col = NULL is never true, and COUNT(col) skips NULLs while COUNT(*) does not.

Follow-up

  • How would you list departments whose average salary exceeds the company-wide average?
  • How do you filter on a window function result such as ROW_NUMBER()?
  • Rewrite a HAVING query as a subquery or CTE filtered with WHERE. When is that clearer?

Describe the implementation of Role-Based Access Control (RBAC) and Identity and Access Management (IAM).

Medium · Database & System Design

Approach

  1. Separate the terms. IAM covers authentication (who you are), authorization (what you may do) and the identity lifecycle: provisioning, deprovisioning, MFA, and SSO via OAuth 2.0/OIDC or SAML. RBAC is one authorization model: permissions are granted to roles and roles to users.
  2. Schema: users, roles, permissions, plus join tables user_roles(user_id, role_id) and role_permissions(role_id, permission_id), each with a composite primary key. Add a scope column such as org_id to user_roles if one person holds different roles in different tenants.
  3. Enforcement in Spring Security: a SecurityFilterChain with authorizeHttpRequests and requestMatchers(...).hasRole("ADMIN") for URL rules, and @EnableMethodSecurity with @PreAuthorize("hasAuthority('member:write')") for method rules. hasRole adds the ROLE_ prefix for you; hasAuthority does not.
  4. Check permissions in code, not role names, so a role can be redefined without code changes. Deny by default and grant least privilege. RBAC alone cannot express "only your own records": that needs an ownership or attribute check (ABAC) on the object.
  5. If roles or permissions are embedded in a JWT, changes only apply when the token expires. Keep tokens short-lived or look permissions up per request, and write role grants and revocations to an audit log.

Follow-up

  • How would you revoke a user's admin role immediately when roles are carried in their JWT?
  • How would you model a doctor who may only view records of patients assigned to them?
  • How do you stop the number of roles from exploding as the product grows?

Create an object-oriented application simulating a healthcare management portal.

Medium · Database & System Design

Approach

  1. Fix the scope first: actors (patient, doctor, admin) and three or four use cases, such as registering a patient, booking and cancelling appointments, recording a visit with a prescription, and viewing history. State what is out of scope, such as billing.
  2. Classes: an abstract Person with Patient, Doctor (specialization, Schedule) and Admin; Appointment (patient, doctor, TimeSlot, and an AppointmentStatus enum with SCHEDULED, COMPLETED and CANCELLED); MedicalRecord holding a list of Encounter and Prescription; services such as AppointmentService that depend on repository interfaces.
  3. Show the OOP principles in the code. Encapsulation: private fields, and state changes through methods that enforce the rules, so cancel() rejects a COMPLETED appointment. Composition: a Doctor has a Schedule rather than inheriting one. Polymorphism: a NotificationSender interface with email and SMS implementations.
  4. Prevent double booking with an overlap check: half-open intervals [s1, e1) and [s2, e2) overlap exactly when s1 < e2 and s2 < e1. Once the data is persisted, back the check with a unique constraint or a row lock, because two threads can both pass an in-memory check.
  5. Use java.time types and an immutable TimeSlot value object. Add access rules, with patients reading only their own records and doctors only their patients', and keep an audit trail of who viewed or changed a record.

Follow-up

  • Two patients book the same slot at the same moment. What stops both from succeeding?
  • How would you add a Nurse role without modifying the existing classes?
  • How would you map these classes to tables with JPA (@OneToMany, @ManyToOne)?

One customer endpoint stalls deliveries to every other destination

Medium · bulkhead · timeouts · saturation

The egress service delivers about 1.5k webhooks/second across 40,000 destinations, with a per-destination concurrency cap of 4 and a 10-second connect-plus-read timeout. Throughput falls to 300/second, queue depth climbs, and p99 delivery latency for unaffected destinations goes from 200 ms to minutes, while the error rate barely moves. One tenant holds 900 destination rows whose URLs share a hostname that now answers in 9.5 seconds. Explain the mechanism with the arithmetic, then give the containment in the order you would apply it.

Approach

  1. Look at saturation before errors. A flat error rate with collapsing throughput says nothing is failing, things are waiting, so the first signal to pull is in-flight request count or pool wait time rather than the error counter. This is the distinction that decides the whole investigation.
  2. Group in-flight work by resolved host, not by destination id. The cap is keyed per destination row, so 900 rows sharing one hostname buy 3,600 concurrent slots against a single host, each held for 9.5 seconds. The bulkhead was never a bulkhead for that host, and grouping by the wrong dimension is why the dashboard looked healthy.
  3. Do the arithmetic in both directions. Required concurrency is arrival rate times latency, so 1.5k/second at 200 ms needs about 300 in flight, which is entirely consumed by 3,600 slow slots; conversely whatever concurrency is left sustains rate equals concurrency divided by 9.5 seconds, which is the 300/second you are seeing. Matching both numbers is what promotes this from a plausible story to the mechanism.
  4. Explain why the circuit breaker never helped. It opens on consecutive failures, and a 9.5-second response inside a 10-second timeout is a success. Slow is not failing, so an error-rate breaker cannot see this; you need a slow-call ratio, a deadline propagated from the caller's remaining budget, or a concurrency limiter.

Follow-up

  • The host recovers to 80 ms. How long does the queue take to drain, and what does the drain do to the recovered host?
  • Where should the 10-second timeout number actually come from?

Suggested practice checklist

Seven days that start from your resume and the Core Java programs, then move through collections and concurrency, Spring Boot and REST, SQL, and security and design, and finish with a full mock of the loop.

Day 1 — Map the loop and audit your resume

  • List the four reported rounds and mark which one you are least ready for
  • List every technology and project on your resume and rate your confidence in each from 1 to 5
  • For your two strongest projects, write the request path from controller to database, including how users authenticate

Deliverable: A one-page loop map, a rated resume inventory and two written architecture walkthroughs

Day 2 — Core Java programs with edge cases

  • Write the reverse-and-palindrome program with a two-pointer check and a StringBuilder version, then run null, empty, single character, mixed case, punctuation and a surrogate pair
  • Write the primes-in-a-range program twice, with trial division to the square root and with a sieve, and test a start below 2 and a start greater than the end
  • Write the balanced-parentheses validator with a Deque, covering (), [] and {}, and test an empty string, a lone closer and leftover openers

Deliverable: Three Java programs, each with a written table of test cases and its time complexity

Day 3 — Collections, concurrency and the language core

  • Run several threads that update a shared HashMap and then a ConcurrentHashMap using merge, and note the lost updates in the first
  • Write a half-page comparison of HashMap and ConcurrentHashMap covering locking granularity, null keys and values, and iterator behavior
  • Make short notes on Java 8 features, checked versus unchecked exceptions, try-with-resources, and heap versus stack memory

Deliverable: A working concurrency demo and a one-page cheat sheet for collections, exceptions and memory

Day 4 — Spring Boot and REST design

  • Outline the member registration module: entity, unique email constraint, request DTO with validation, repository, transactional service, controller, and the status codes returned
  • Write a short explanation of annotations such as @RestController, @Service, @Repository and @Bean, and of constructor injection
  • Write a clear answer to the web services versus APIs question, using HTTP-based services as a subset of APIs

Deliverable: A member registration design sheet with the schema and annotations, plus a spoken one-minute answer on web services versus APIs

Day 5 — SQL and indexing

  • Create a small members and orders dataset locally and write queries that use WHERE alone, then GROUP BY with HAVING, and explain which rows each clause removes
  • Run EXPLAIN on a slow filter-and-sort query, add a composite index, and compare the plans
  • Write down rules for index design: column order, selectivity, covering indexes and the write cost of each extra index

Deliverable: A set of worked WHERE and HAVING queries and a before-and-after query plan with a written index rationale

Day 6 — Access control and object-oriented design

  • Sketch a role-based schema with users, roles, permissions and join tables, and map it to Spring Security method-level checks
  • Write a short note separating RBAC, which is one access model, from IAM, which covers identities, authentication, authorization and auditing
  • Design the healthcare management portal as classes, such as patients, doctors, appointments and a scheduling service, with a conflict check for overlapping appointments

Deliverable: A role-permission schema, a note on RBAC versus IAM and a class diagram for the portal

Day 7 — Mock loop and scenario stories

  • Do a full spoken run: a resume architecture walkthrough, one coding program written live while narrating, and one SQL answer
  • Write and rehearse three scenario stories on tight deadlines, changing requirements and AI tools in your workflow

Deliverable: One recorded or timed mock run and three scenario stories in situation, action, result form

Deadlines, clients and resume deep dives

Candidates describe the later rounds as covering scenario questions about tight deadlines and client expectations, plus your view on AI tools and continuing to learn. For a Java backend role, back each story with a concrete delivery detail such as a module you owned, a schema change or an API contract.

  1. Explain the end-to-end architecture of a project from your resume, including API flows and authentication implementation.
  2. Tell me about a time you had a tight deadline. What did you cut, what did you protect, and how did you report status?
  3. Describe a time a client or stakeholder changed requirements late. How did you adapt the design and the schedule?
  4. How do you use AI-assisted tools in your development workflow, and how do you verify what they produce?
  5. Describe a technology you had to learn quickly for a project and how you got productive with it.

Narrate an outage you owned from page to postmortem

Hard · incident response · blast radius · postmortems

Pick an incident you personally drove, ideally one where writes were affected rather than reads. In six to eight minutes: state the symptom as it first appeared on a dashboard, the blast radius you established before you knew the cause, the mitigation you applied and when, the mechanism you eventually proved, and the follow-up that would prevent a repeat. Bring numbers: error rate, tenants affected, minutes to mitigate, minutes to resolve. If you cannot name what you measured, choose a different incident.

Approach

  1. Open on the signal rather than the cause: which metric at which percentile moved, on which service, at what time, so the listener follows the same evidence you had rather than a conclusion you already reached.
  2. Separate mitigation from diagnosis out loud. State what you did to stop the bleeding (flag off, shed traffic, drain a lease, roll back a deploy) and say plainly that you did it before the mechanism was known, because those are two jobs with different deadlines.
  3. Establish blast radius in countable terms: how many tenants, how many writes, and crucially whether the effect was loss or only delay. An append-only revision table or a pending outbox row means the change survived and the projection was merely behind, which is a repair rather than a data-loss incident.
  4. Prove the mechanism instead of asserting it. Name the trace span that grew, the plan that flipped to a sequential scan, the lease that expired, plus one alternative you ruled out and the signal that stayed flat while you ruled it out.

Follow-up

  • What would you do differently in the first five minutes, given the same dashboard and no more information?
  • Which follow-up action did you deliberately not take, and why was dropping it the right call?

Estimate work you have never done and defend the range

Hard · estimation · backfills · expand-contract

You are asked to estimate a change you have never attempted: add a column to a 100-million-row table, populate it, move reads across, and drop the old shape. Give a range with the assumptions that generate it, including batch size, the signal your backfill throttles on, and wall-clock hours, and name the three unknowns that would move the number most. Then describe a real estimate you gave under comparable ignorance: how you expressed its uncertainty, what you committed to, and how wrong you turned out to be.

Approach

  1. Decompose into independently deployable steps before estimating anything: add the column nullable, write both shapes, backfill in batches, verify, move reads, stop writing the old shape, drop it. That is four deploys spread over days, and the calendar estimate is dominated by them rather than by the loop's runtime.
  2. Do the arithmetic aloud for the part that has arithmetic in it: batch size times number of batches times per-batch duration, at a write rate the primary can absorb alongside roughly 1.2k writes per second of production traffic. The loop is throttled by replication lag and lock waits, not by how fast it can issue statements.
  3. Price the schema step by its lock rather than its statement duration. In PostgreSQL an ALTER TABLE taking ACCESS EXCLUSIVE waits for every open transaction on that table while later queries queue behind it, so a millisecond change issued during a thirty-second analytics query stalls that table for thirty seconds. Adding a nullable column with a non-volatile default avoids a rewrite from version 11; a new index wants CREATE INDEX CONCURRENTLY, which cannot run inside a transaction block and leaves an invalid index behind if it fails.
  4. Express the answer as a range whose endpoints each trace to a stated assumption, then name the cheapest experiment that collapses it, which is almost always running one real batch against the real table and multiplying.

Follow-up

  • How do you verify the backfill genuinely finished, given rows written by production traffic while it ran?
  • Where does the backfill resume from after a worker is killed mid-batch, and what makes that resume point trustworthy?

Ship under a deadline and bound the debt you chose

Medium · pagination · technical debt · tradeoffs

You have four days to ship a tenant-facing listing endpoint. The version you would defend uses keyset pagination over (tenant_id, status, updated_at DESC, resource_id DESC); the version you can finish uses LIMIT/OFFSET with no matching index. Describe a deadline call you actually made of this shape: what you shipped, what you knowingly deferred, how you bounded the damage with a mechanism rather than an intention, and the specific numeric condition that would force the follow-up. Name who you told and where you wrote it down.

Approach

  1. Name the deferred failure precisely instead of calling it slow. OFFSET n makes the database produce and discard n rows, so cost grows with page depth; without an index matching the sort, every matching row is read and sorted before the limit applies; and rows inserted between two page fetches shift across the boundary so items are skipped or repeated with nothing in the response to signal it.
  2. Bound the blast radius with something mechanical rather than a promise: cap maximum page depth, cap page size, restrict the endpoint to one internal caller, or keep it behind a flag. State which failure each cap removes and which it leaves standing.
  3. Attach a number to the trigger and wire it to an alarm: the first tenant crossing N resources, or the endpoint's p99 crossing its share of the 400 ms budget, so the debt announces itself instead of waiting to be remembered.
  4. Write it where the next engineer looks, which is the code and the ticket, not a chat message: what was deferred, why, the cap, and the trigger.

Follow-up

  • At what page depth does the offset version breach your latency budget, given your page size and row counts?
  • What breaks first when you switch to keyset pagination later, and what does a client holding an old page token see?