cswork / libraryOpen practice workspace

Interview guides · Avangarde Consulting Group

Avangarde Consulting Group Software Engineer Interview Guide

Avangarde Consulting Group Software Engineer interview guide: Java, OOP, debugging and project deep-dive questions with answers and a 7-day plan.

The 60-second brief

Avangarde Consulting Group is a consulting firm that delivers software projects for clients, and candidates report that engineers may also be placed on projects for partner companies. The Software Engineer role candidates describe is backend work in Java: designing, building and maintaining the services behind client applications, taking work from requirements and technical specification through implementation and testing, reviewing code, turning business requirements into technical tasks, reporting progress to project managers or clients, and fixing issues raised in testing or production. Much of the work happens inside codebases someone else wrote, so reading unfamiliar code fluently is part of the job.

This guide is for engineers interviewing for the Software Engineer role at Avangarde Consulting Group, usually with a Java backend background. It covers the reported stages, question-by-question guidance for the four Java and backend questions and five behavioral questions candidates report, the wider stack in the requirements candidates describe (SQL/databases and Git as must-haves; AWS or Azure, microservices and Agile/Scrum as nice-to-haves), and a one-week plan that ends in a full mock of the process.

Candidates report three stages over roughly two weeks: an introductory (conoscitivo) interview about background and goals, a technical assessment that usually centres on Java, and a final deep-dive with a senior developer covering past projects and live problem solving.

Focus areas

  • Java
  • Back-end development
  • Problem solving (in colloqui di programmazione)

Overview

The reported questions fall into two groups. Four are technical: OOP principles in Java, how you debug a complex backend application, memory management and performance in Java services, and refactoring legacy code. Five are behavioral and lean on consulting situations: a challenging project and your own part in it, technical disagreements with teammates or clients, learning a framework on a deadline, meeting a client's quality bar, and documentation on long-running projects. Candidates also mention a live coding exercise, with sample prompts such as processing a given data structure efficiently and speeding up an existing piece of code.

On the technical side, the areas candidates list are Java Collections, multithreading, exception handling, basic data structures and algorithms, and when to use Singleton, Factory or Strategy. That is a fundamentals-heavy scope: prepare to explain why a HashMap depends on a consistent equals and hashCode, when an ExecutorService beats managing raw threads, and where checked exceptions belong, and to write correct Java without an IDE filling in the APIs. Candidates describe the assessments as tests of core knowledge and reasoning rather than trick problems, so depth on fundamentals pays more than rare algorithms.

The final stage is reported as a conversation with a senior developer about projects you have built, plus problem solving in real time. Prepare two projects you can defend at the level of architecture, data model, the trade-offs you made and the code you personally wrote. Because the role involves explaining technical constraints and progress to project managers and clients, practise giving each technical answer in a version a non-engineer could follow as well.

The requirements candidates describe also list SQL/databases and Git as must-haves. Neither appears in the reported questions, but a Java backend assessment can reach a join, an index or a transaction, so cover joins, aggregation, indexing and isolation levels, and be able to explain merge versus rebase and how you resolve a conflict.

Where to focus your preparation

Candidates report an introductory interview, a Java-focused technical assessment and a deep-dive with a senior developer; the step below covers what to prepare across all three.

Preparation focus

Candidates report three stages. The process opens with an introductory (conoscitivo) interview about your background and professional goals. A technical assessment follows, usually centred on Java. The last stage is a deep-dive with a senior developer in which you discuss past projects and solve technical problems in real time, and candidates also mention a live coding exercise. Prepare in that order: a short career summary and clear reasons for wanting consulting work, then Java fundamentals and small coding problems written by hand in Java, then two project stories you can defend down to individual design decisions. Candidates say the way you reason through a coding problem counts alongside the final answer, so practise every coding problem out loud.

What to demonstrate

  • Your background and goals, reported as the subject of the introductory interview
  • Core Java knowledge, which candidates report the technical assessment centres on
  • Working Java code in the live coding exercise, with the reasoning stated as you write it
  • How well you explain and defend the design of your past projects in the senior-developer deep-dive

How to prepare

  • Rebuild the reported Java areas: Collections internals (HashMap, ArrayList, TreeMap, ConcurrentHashMap), exception handling, ExecutorService-based multithreading, and Singleton, Factory and Strategy with one code example each
  • Solve five or six small data-structure problems in plain Java without autocomplete while narrating, such as the overlapping job attempts and heaviest tenants practice problems, plus one task that speeds up an existing slow method
  • Write out two project stories covering architecture, data model, one trade-off, one production issue you fixed and the code you personally wrote
  • Prepare a career summary and questions about project allocation, partner-company placements and smart working for the introductory interview

Where candidates lose points

Reciting encapsulation, inheritance, polymorphism and abstraction as textbook definitions with no Java code behind them.

For each principle, have one snippet from your own work ready: an immutable value class, an interface with two implementations chosen at runtime, a place where you swapped inheritance for composition. Know the equals/hashCode contract and the interface versus abstract class rules well enough to state them without hesitation.

Answering the debugging question with 'I add print statements' and no order of attack.

Learn a fixed sequence: scope and reproduce, read logs by request id and the full stack trace, check metrics, then pick a tool by symptom (thread dumps for hangs, heap dumps for memory growth, a profiler for slowness), fix with a regression test. Tell it through one real incident you resolved.

Coding the live exercise in silence, or depending on an IDE for Java syntax and collection APIs.

Candidates report that explaining your logic during coding exercises carries weight. Practise in a plain editor while talking: restate the input, give the simple approach and its complexity, then improve it. Know Map.getOrDefault, computeIfAbsent, PriorityQueue, ArrayDeque and Comparator chaining from memory.

Going vague in the project deep-dive: unable to say why an architecture or library was chosen, or which part you wrote.

For two projects, write down the components and how they talk to each other, the data model, one trade-off with the rejected alternative, one production problem and how you fixed it, and the code that was yours. Rehearse answering 'why not X instead?' for each major choice.

Skipping SQL and Git because the reported questions are Java-heavy.

The requirements candidates describe list SQL/databases and Git as must-haves. Review joins, GROUP BY with HAVING, when an index is and is not used, transactions and isolation levels, and the N+1 problem in JPA or JDBC code; be able to explain merge versus rebase and how you resolve a conflict.

Questions & practice

Diff a projection against the primary without per-row point reads

Hard · reconciliation · range hashing · throttling

The listing projection has drifted and some rows show a stale version. The primary holds 40,000,000 resource rows across 12,000 tenants while serving 1,200 writes and 14,000 reads per second. The obvious repair, reading each resource row and comparing its version against the projection, is correct and would eventually finish. Explain precisely why it is unacceptable here, then give a diff that finds the differing rows, state its complexity, and make it safe to run against a live primary. Replication lag is usually under 100 ms and is not bounded.

Approach

  1. Quantify the naive cost rather than calling it slow: 40,000,000 point reads at even 0.5 ms each is over five hours serialised, and the only lever is concurrency, which is exactly what you cannot spend. The primary's pool is sized for the write path, and 40,000,000 random reads evict the buffer cache that sustains the 85 percent cache hit rate, so the audit degrades the system it is auditing.
  2. Replace random access with one ordered pass per side. Both sides can be read in (tenant_id, resource_id) order, which is a sequential scan on each and a merge join in O(n) time and O(1) memory. For a dense diff that is the whole answer, and it reads the primary once instead of 40,000,000 times.
  3. For the expected sparse case, compare range hashes instead of rows: partition the key space, compute per range an order-independent aggregate over hash(resource_id, version), compare aggregates, and descend only into ranges that differ. With d differing rows and branching factor B, at most d ranges mismatch per level, so the drill-down examines O(d log_B(n/d)) ranges and reads full rows only in mismatching leaves.
  4. Aggregate with a sum modulo 2^64 or a multiset hash, never XOR. XOR is order-independent but self-cancelling, so two rows wrong in the same way, or a row duplicated on one side, leave the range aggregate matching and the range is declared clean.

Follow-up

  • The diff reports 900 stale rows. How do you decide between patching those rows and rebuilding the projection from resource_revision?
  • Same job, but the projection lives in a search index that cannot be scanned in key order. What changes?

Identify the heaviest tenants in a five-minute window under memory pressure

Medium · top-k · heavy hitters · streaming

The edge service handles about 3,000 requests per second across roughly 50,000 tenants, peaking near 9,000. Expose the 50 heaviest tenants by request count over the trailing five minutes so limits can be tightened before one tenant's backfill starves the fleet. You may not retain five minutes of raw records. Give the exact solution and its memory, then the bounded-memory approximation with its error stated as a formula, and say which you would ship and at what tenant cardinality that choice changes.

Approach

  1. Do the exact version first, because it is affordable at this cardinality: a ring of 300 one-second counters per tenant, advanced lazily, is 1,200 bytes of counters per tenant and roughly 60 to 90 MB for 50,000 tenants with overhead. Carry a running total and subtract the bucket you overwrite so a window read is O(1) rather than 300 adds.
  2. Extract the top 50 with a size-k min-heap over the tenant sums: O(d log k) for d tenants, against O(d log d) to sort them all. Maintaining the heap continuously instead of on query requires a tenant-to-heap-index map, because incrementing a count already inside the heap means sifting from a known position, and without that map you rebuild the heap on every request.
  3. State the approximation precisely rather than gesturing at sketches. Misra-Gries with m counters retains every item whose true count exceeds N/(m+1), and each retained count underestimates the truth by at most N/(m+1). With m = 1,000 and N = 900,000 requests in the window the error is roughly 900 requests, which is fine for spotting a tenant sending 50,000 and useless for ranking two tenants 200 apart.
  4. Say what breaks when the window slides: Misra-Gries and Space-Saving are insert-only and cannot be decremented as records age out. The workable construction is one summary per sub-window, say ten seconds, with 30 summaries merged at query time, and the merged error is the sum of the per-summary errors, so the bound degrades linearly in the number of sub-windows.

Follow-up

  • The heaviest tenant is heavy because of one export job rather than user traffic. Should the limiter treat those as the same tenant?
  • Two tenants sit tied at the boundary of the top 50. Does your answer flap, and does the flapping matter?

Find overlapping job attempts and peak concurrency from lease records

Medium · sweep line · intervals · leases

A day of job_run history yields about 50,000,000 attempt records: (job_run_id, job_type, attempt, started_at, finished_at which is NULL when the worker died, lease_expires_at). Leases expire on a clock, so a job that outran its lease ran twice. Produce (a) every job_run_id whose attempts overlapped in wall-clock time and (b) the peak number of simultaneously running attempts per job_type with the minute it occurred. Target O(n log n). State how you treat a NULL finished_at and what clock skew does to your answer.

Approach

  1. Define the interval before sorting anything: an attempt occupies [started_at, COALESCE(finished_at, lease_expires_at)). finished_at is observed and lease_expires_at is only a promise, so every attempt without a finish contributes an estimate and the whole result is a lower bound on overlap rather than an exact count.
  2. For peak concurrency, sweep: emit 2n endpoints, sort by (timestamp, kind) with ends ordered before starts at equal timestamps, then walk the sequence maintaining a counter per job_type and record each type's maximum with its timestamp. O(n log n) dominated by the sort, O(n) space, or O(1) extra if the sort is external and the walk streams.
  3. For overlap detection, do not compare attempts pairwise. A single global sort by (job_run_id, started_at) gives both the grouping and the order; within a group, keep the maximum end seen so far and report an overlap exactly when the next start is less than that running maximum, which is one linear pass after the sort.
  4. Half-open intervals matter and are easy to get wrong: with closed intervals an attempt ending at the same millisecond another begins reads as concurrency two, and across 50,000,000 records that artefact swamps the real signal.

Follow-up

  • A handler is not idempotent and you have found 400 overlapping jobs. Which of them actually caused damage, and what would you query to find out?
  • Peak concurrency for one job_type is 4 against a configured cap of 4. Is the cap working, or is the data hiding attempts that never started?

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?

Stop tag and share joins from fanning out a page

Medium · join fan-out · semi-joins · many-to-many

resource_tag is (resource_id, tag_id) with PK (resource_id, tag_id); resource_share is (resource_id, shared_with_user_id, permission). The tagged-and-shared listing inner-joins resource to both, filters tenant_id, tag_id = ANY($2) and shared_with_user_id = $3, orders by updated_at DESC and takes 50. Pages come back with fewer than 50 distinct resources and the total in the header is far too high. Explain the row multiplication, rewrite both the page query and the count query so each is correct, and name the index each one needs. PostgreSQL 16.

Approach

  1. Do the arithmetic against the predicates that are actually there. An inner join emits one row per matching child row, and both joins are filtered: tag_id = ANY($2) admits only the requested tags, shared_with_user_id = $3 admits one user's share rows. So a resource holding three of the requested tags and shared with $3 once yields three rows, not one — the multiplier is its count of matching tags times its share rows for that single user, and that second factor is 1 unless the table admits duplicate (resource_id, shared_with_user_id) pairs. LIMIT 50 then limits rows rather than resources, and COUNT(*) counts pairs — the header is the product, not the population.
  2. Reject DISTINCT as the fix. It deduplicates after the product has been built, so the planner must materialise and sort the fanned-out set before the LIMIT can apply, and it leaves any SUM or AVG in the same select list wrong.
  3. Rewrite both filters as semi-joins, keeping resource as the only row source: AND EXISTS (SELECT 1 FROM resource_tag rt WHERE rt.resource_id = r.resource_id AND rt.tag_id = ANY($2)) and the same shape against resource_share. A semi-join stops at the first match per resource and preserves the driving index order, so ORDER BY updated_at DESC, resource_id DESC LIMIT 50 still stops after 50 rows.
  4. Count with the same predicates and no join at all: SELECT count(*) FROM resource r WHERE r.tenant_id = $1 AND r.status = 'active' AND EXISTS (...) AND EXISTS (...). Nothing multiplies a resource, so the number is the population.

Follow-up

  • The filter changes from 'any of these tags' to 'all of these tags'. Rewrite it and state what it costs relative to the ANY form.
  • A resource can be shared with the same user twice under different permissions. Does your count change, and should it?

Explain the core principles of Object-Oriented Programming (OOP) and how you apply them in Java.

Medium · Technical Proficiency and Java

Approach

  1. Name the four principles and attach a Java mechanism to each: encapsulation (private fields, validation in constructors, final fields and defensive copies for immutable value objects), inheritance (extends for a genuine is-a relationship), polymorphism (overriding resolved at runtime by dynamic dispatch, versus overloading resolved at compile time) and abstraction (interfaces and abstract classes that hide implementation).
  2. Show application rather than definitions: code to interfaces (List<Order> orders = new ArrayList<>()), inject dependencies through constructors, and replace a growing if/else on a type field with a Strategy interface and one implementation per case, chosen by a Factory.
  3. Say when you avoid inheritance: prefer composition when a subclass would only reuse code, because deep hierarchies couple subclasses to parent internals and can break the Liskov substitution principle (the Square-extends-Rectangle case).
  4. Cover the Java specifics: interface versus abstract class (state and constructors only in abstract classes, default methods since Java 8, many interfaces but one superclass), and the equals/hashCode contract that HashMap and HashSet rely on.

Follow-up

  • When would you choose an abstract class over an interface in current Java?
  • What breaks if you override equals but not hashCode, and how would you notice it?
  • Show how Strategy or Factory uses polymorphism in a service you have written.

Describe a situation where you had to refactor legacy code to improve maintainability.

Medium · Technical Proficiency and Java

Approach

  1. Use STAR but spend most of the answer on method. Situation: what made the code hard to change (a class of thousands of lines, duplicated logic, no tests) and what that cost the project (slow changes, repeat defects).
  2. Describe the safety net first: characterization tests that pin current behaviour, odd cases included, before touching anything; then small commits that each keep the build green.
  3. Name the refactorings: extract method and extract class to split responsibilities, introduce an interface plus constructor injection to make dependencies testable, replace type-switching conditionals with polymorphism, and for larger pieces the strangler fig approach of routing calls to new code step by step.
  4. Explain how it fitted into delivery: refactoring the code a feature already touched, agreeing scope with the project manager or client, and using code review to keep teammates aligned.
  5. End with evidence: faster subsequent changes, fewer regressions, higher coverage, and what you deliberately left alone because the risk outweighed the gain.

Follow-up

  • How did you make sure the refactor did not change behaviour?
  • How did you justify the time to a project manager or client focused on features?
  • What would you do with no tests and no time to write many?

Can you walk me through your process for debugging a complex backend application?

Medium · Technical Proficiency and Java

Approach

  1. Start with scope and reproduction: which endpoint, which users, since when, and whether a deploy, configuration change or data change lines up with the start. Get a reliable reproduction outside production before changing code.
  2. Read the evidence in order: logs filtered by a correlation or request id across services, the full stack trace including the Caused by chain, then metrics such as latency, error rate, heap usage and connection-pool saturation.
  3. Pick the JVM tool by symptom: for a hang, take several jstack thread dumps a few seconds apart and look for BLOCKED or deadlocked threads; for growing memory, a heap dump (jmap or -XX:+HeapDumpOnOutOfMemoryError) inspected for the largest retained objects; for slowness, a profiler such as Java Flight Recorder.
  4. Halve the search space: disable one dependency, replay a single request, or run git bisect between a known-good and a bad commit. Attach a remote debugger only outside production.
  5. Close the loop: write a failing test that reproduces the bug, fix the root cause rather than the symptom, confirm with the same metric that showed the problem, and add logging or an alert so a recurrence is quicker to find.

Follow-up

  • The bug only appears in production and you cannot reproduce it locally. What do you do?
  • A request hangs and nothing is logged. What does a thread dump tell you?
  • How do you show the fix worked rather than that the symptom happened to stop?

Suggested practice checklist

Each day targets one part of the reported process: Java fundamentals and coding for the technical assessment, debugging, performance and SQL for the backend questions, project stories for the senior-developer deep-dive, and the consulting behavioral questions. Reported and practice questions are attached to the days that work them.

Day 1 — Java OOP and design patterns

  • Answer the OOP principles question aloud, giving a Java code example for each of the four principles
  • Write a small fee calculator in Java with a Strategy interface, two implementations and a Factory that picks one at runtime
  • Write an immutable value class with correct equals and hashCode, and a test that stores and finds it in a HashSet

Deliverable: A recorded OOP answer, a working Strategy plus Factory example, and an immutable value class with a passing HashSet test.

Day 2 — Collections and data-structure coding

  • Review HashMap internals (hashing, buckets, resizing, tree bins since Java 8), ArrayList versus LinkedList, TreeMap, PriorityQueue and ConcurrentHashMap
  • Solve the overlapping job attempts problem in Java: sort by start time and sweep with a min-heap of end times to get peak concurrency, narrating as you go
  • Solve the heaviest tenants problem in Java: count with a HashMap and keep a size-k min-heap for O(n log k), then discuss what changes when memory is tight

Deliverable: A one-page Collections cheat sheet and two narrated Java solutions with their complexity written down.

Day 3 — Memory, performance and concurrency

  • Answer the memory management and performance question aloud with one real optimisation story and its before and after number
  • Write a program with an unbounded static cache, run it with a small -Xmx, capture a heap dump and identify the retaining map
  • Write a producer-consumer with ExecutorService and a BlockingQueue, and explain synchronized versus volatile versus AtomicInteger
  • Take a slow method (string concatenation in a loop, autoboxing, wrong collection) and rewrite it, measuring both versions

Deliverable: A recorded performance answer, an annotated heap-dump finding, a working producer-consumer, and a before and after timing for the rewritten method.

Day 4 — Backend debugging and SQL

  • Write your debugging sequence as a one-page checklist and tell one real debugging story with it aloud
  • Create a deliberate deadlock between two threads, take jstack dumps and point to the lock cycle
  • Solve the per-tenant active cap SQL problem (transaction with a row lock or a guarded insert) and the tag-and-share fan-out problem (aggregate before joining)
  • Revise Git merge versus rebase and how you resolve a conflict

Deliverable: A debugging checklist plus recorded story, an annotated thread dump, two SQL solutions with the concurrency or fan-out reasoning, and Git notes.

Day 5 — Project deep-dive stories

  • For two projects, write the component sketch, data model, one trade-off, one production issue and the code you personally wrote
  • Build the legacy refactoring story around characterization tests, named refactorings and a measurable result
  • Build the challenging-project story with your own contribution and a concrete outcome, then explain each project once for an engineer and once for a non-technical client

Deliverable: Two project fact sheets and recorded STAR answers for the refactoring and challenging-project questions.

Day 6 — Consulting behavioral answers

  • Write STAR outlines for the disagreement, learning-under-deadline, client quality standard and documentation questions
  • Rehearse each aloud and cut anything that does not show your own decision or a result
  • Write questions for the interviewers about project allocation, partner-company placements, training and smart working

Deliverable: Four rehearsed STAR outlines and a list of questions to ask.

Day 7 — Full mock of the three stages

  • Mock the introductory interview: career summary, why consulting, what you want from your next project
  • Mock the technical stage: solve the projection-diff problem in Java (sorted merge or hash comparison in batches instead of per-row reads), then answer rapid Java questions on Collections, exceptions and threads
  • Mock the deep-dive: have someone question you on one project and one technical problem, then re-do the weakest answer

Deliverable: A completed three-part mock, a written list of weak spots, and one re-done answer.

Behavioural preparation

The behavioral questions candidates report centre on consulting situations: owning your part of a hard project, resolving technical disagreements with teammates or clients, picking up new technology quickly, meeting a client's quality bar and keeping long-running projects documented. Prepare one first-person STAR story per prompt, each ending in a concrete result.

  1. Describe a situation where you had to refactor legacy code to improve maintainability.

How do you handle memory management and performance optimization in Java-based services?

Medium · Technical Proficiency and Java

Approach

  1. Lay out the JVM memory model: objects live on the heap, which the garbage collector manages in young and old generations; each thread has its own stack for frames and local variables; class metadata lives in Metaspace. Know that G1 has been the default collector since Java 9 and that -Xms and -Xmx bound the heap.
  2. Explain that a Java leak is memory still referenced, not memory never freed: unbounded static maps or caches, listeners never removed, ThreadLocal values left on pooled threads, unclosed streams and connections. Remedies are try-with-resources, bounded caches with eviction, removing ThreadLocal values in finally blocks, and weak references where they fit.
  3. Describe a measure-first workflow: reproduce the load, profile with Java Flight Recorder or VisualVM, read GC logs for pause length and frequency, and take a heap dump and inspect the dominator tree when old-generation usage keeps climbing after full collections.
  4. Name the fixes that usually matter in backend services before any JVM flag: N+1 database queries, missing indexes, connection-pool sizing, string concatenation in loops (use StringBuilder), autoboxing in hot paths, and the wrong collection (LinkedList for indexed access, a HashMap resized repeatedly instead of created with a capacity).
  5. Anchor it with one real case: the symptom, the measurement that pinpointed it, the change, and the before and after number such as p95 latency, heap after GC or pause time.

Follow-up

  • OutOfMemoryError: Java heap space versus Metaspace: what does each point to?
  • How would you find a leak in a running service without restarting it?
  • Why can a hand-written microbenchmark mislead you, and how does JMH help?

Tell me about a challenging project you worked on and your specific contribution to its success.

Medium · Behavioral and Professional Experience

Approach

  1. Choose a project where the difficulty was real and you owned a clear piece, ideally backend work in Java; a project you only watched will not hold up under detailed questions about its design.
  2. Situation and task in a few sentences: the system, the constraint (deadline, legacy integration, performance target, shifting requirements) and what you were responsible for.
  3. Actions in the first person: the decision you made, the alternative you rejected and why, and how you kept the team, project manager or client informed. Separate your work from the team's explicitly.
  4. Result with a number or concrete outcome (shipped on a date, latency from A to B, defects down) plus one thing you would do differently. The mistake that sinks this answer is narrating the team's achievement without ever stating your own contribution.

Follow-up

  • What would have gone wrong if you had not done your part?
  • Walk me through the architecture of that system.
  • What would you change if you started the project again?

How do you handle disagreements regarding technical implementation with team members or clients?

Medium · Behavioral and Professional Experience

Approach

  1. Pick a real disagreement over an implementation choice (framework, data model, synchronous versus asynchronous integration, scope of a fix) where the stakes were concrete.
  2. Show the method: understand the other side's reasons first, agree the decision criteria (requirements, risk, delivery date, maintenance cost), then settle it with evidence such as a small prototype, a benchmark or a written comparison of options.
  3. For a client disagreement, translate the technical constraint into cost, risk and timeline, present options with their consequences, let the client decide where the call is theirs, and record the decision in writing.
  4. Include the outcome and your conduct afterwards: if the decision went against you, show that you committed to it. Avoid stories where the other person was simply wrong or where nothing was resolved.

Follow-up

  • Tell me about a time you turned out to be the one who was wrong.
  • What if the client insists on an approach you believe is risky?
  • When do you escalate instead of resolving it yourself?

Describe a time when you had to learn a new technology or framework under a tight deadline.

Medium · Behavioral and Professional Experience

Approach

  1. Pick a case with a real deadline and a technology new to you (a framework, a database, a cloud service, a client's internal platform), and say what was at stake if you missed it.
  2. Describe how you learned efficiently: mapped the new tool onto concepts you already knew, read the official documentation, built a small throwaway spike on the hardest part first, and asked someone experienced to review your first pull request.
  3. Show you protected quality: what you tested, which shortcuts you took on purpose and how you paid them back afterwards.
  4. Close with the result and the habit you kept. Candidates report that consultants move between client projects, so link the story to how you would ramp up on an unfamiliar client codebase.

Follow-up

  • How did you decide you knew enough to ship?
  • What did you get wrong because the technology was new to you?
  • How would you become productive in an unfamiliar client codebase in your first week?

How do you ensure that your code meets the quality standards expected by the client?

Medium · Behavioral and Professional Experience

Approach

  1. Start by establishing the client's standard: coding conventions, Definition of Done, required coverage, static-analysis or security gates, review rules. Quality is judged against that bar, not only your own.
  2. List the practices you apply every time: JUnit unit tests with mocked dependencies, integration tests at database and API boundaries, deliberate exception handling and logging, small pull requests, and review on every change.
  3. Mention automation: a CI pipeline that runs tests and static analysis (for example Checkstyle or SonarQube) on every push, so the standard is enforced by the build rather than by memory.
  4. Back it with one example, such as a defect you caught in review or with a test before it reached the client, and address deadline pressure: what you would never skip and what you would negotiate.

Follow-up

  • What do you look for first when reviewing someone else's pull request?
  • The deadline is tomorrow and the tests are not written. What do you do?
  • How do you handle a client standard you disagree with?

What is your approach to documentation when working on long-term projects?

Medium · Behavioral and Professional Experience

Approach

  1. Say what you document and where: a README that gets a new developer running locally, architecture decision records explaining why a choice was made, API contracts (OpenAPI, or Javadoc on public interfaces), and runbooks for deployment and common incidents.
  2. Keep it beside the code and current: documentation lives in the Git repository, changes in the same pull request as the code it describes, and is checked in review; code comments explain why, not what.
  3. Tie it to consulting work: candidates report that consultants move between client projects, so handover notes and decision records are what let the next engineer continue without you.
  4. Give one example where documentation saved time, or where its absence cost time, and what you changed afterwards.

Follow-up

  • How do you stop documentation going stale?
  • What would you write before handing a project to another consultant?
  • What belongs in a code comment and what belongs in external documentation?