cswork / libraryOpen practice workspace

Interview guides · AIG

AIG Software Engineer Interview Guide

AIG Software Engineer interview guide: 4 reported rounds, Java, Spring Boot, MuleSoft and MongoDB questions, system design and a 7-day prep plan.

The 60-second brief

AIG is a global insurance organization; candidates describe it as operating across roughly 190 countries and jurisdictions. Reports describe technology as part of underwriting, claims processing and defending internal systems against security threats. Candidates describe the role as building software applications for those functions. The work as candidates describe it spans enterprise integration services written with MuleSoft or Java, microservices on Spring Boot, Angular front ends that call REST services, cloud work on AWS, CI/CD pipelines, and data access across relational and NoSQL stores. Candidates describe the work as happening in Agile teams alongside product owners and IT leads.

This guide is for candidates interviewing for a Software Engineer position at AIG. It walks through the four reported rounds, gives preparation notes for the reported technical, design, coding and behavioral questions, and ends with a seven-day plan. It does not cover other AIG roles or compensation.

Candidates report four rounds over about three to five weeks: Recruiter Screening, Virtual/Panel Interviews, Technical Evaluation and Behavioral Evaluation. The format and the number of rounds may differ depending on the team, the location and the level of the role.

Focus areas

  • Java
  • SailPoint IdentityIQ (IGA)
  • Identity Lifecycle Management

Overview

The requirements candidates describe for this role combine Java or Python with object-oriented design, microservices (Spring Boot or an integration platform such as MuleSoft), hands-on work with relational and NoSQL databases, CI/CD, automated testing and Agile delivery. Nice-to-have items are AWS, Terraform, Docker, Kubernetes, Angular, cloud or integration certifications, and prior work in enterprise or financial-services settings. Use that list to decide where you need depth and where you only need to speak accurately about what you have used.

The reported questions fall into four groups. Technical and domain questions cover integration services, a MongoDB aggregation that uses preserveNullAndEmptyArrays, memory leaks in production, and secure identity lifecycle management. Design questions cover Spring Boot microservices on AWS, wiring an Angular front end to REST services, CI/CD pipeline design, and database access across relational and NoSQL stores. Behavioral questions cover working with stakeholders, deadlines against quality and technical debt, troubleshooting under pressure, and mentoring. Coding questions cover a Caesar Cipher style string task, easy-to-medium algorithm problems, unit tests that include exception paths, and a data transformation pipeline. Expect breadth, so rehearse each group, then go deep on the stack that appears on your own CV.

The topic breakdown candidates report lists Java next to SailPoint IdentityIQ, identity lifecycle management, access provisioning and deprovisioning, and entitlement management. The reported identity question is phrased in general terms, so prepare the concepts instead of a single product: how an account is created when someone joins, changed when they move teams, and removed when they leave; how entitlements are requested, approved and reviewed; and how you would prove who had access to what. If you have used an identity governance tool, say so and describe what you configured.

Candidate tips repeat three habits: say your assumptions and trade-offs aloud while you code or design, have project deep dives ready with your own contribution made clear, and mention testing and security without being asked. The plan in this guide turns those habits into daily exercises, so each day ends with something you can reread or say aloud.

The AIG interview process

These are the four stages candidates describe, in the order they report them. Which of them you meet, and in what format, can depend on the team.

Recruiter Screening

Candidates describe the first stage as a conversation with a recruiter about your background, your interest in technology and how well you line up with the role's core technical requirements. Treat it as the point where your stack becomes visible: the requirements candidates describe name Java or Python, Spring Boot or MuleSoft, relational and NoSQL databases, CI/CD and Agile delivery, so be ready to say which of those you have used in real projects and at what depth.

What to demonstrate

  • How your background maps onto the role's core technical requirements
  • Your stated interest in technology and in this role

How to prepare

  • Write a short career walkthrough that names the languages, frameworks and data stores from your CV that match the requirements, with one concrete deliverable for each.
  • List which items from the requirements and nice-to-haves (AWS, Terraform, Docker, Kubernetes, Angular) are strong, which are working knowledge and which you have not used, and be ready to say so plainly.
  • Ask the recruiter what the technical evaluation will look like for this team, since candidates report that live coding, architecture discussion and assessment platforms vary by team.

Virtual/Panel Interviews

Candidates report a series of virtual or panel interviews with hiring managers, technical leads and engineering peers. Because the audience is mixed, prepare each project twice: a short version that states the business problem and your result, and a detailed version that covers architecture, your own contribution, one design decision with its trade-off and one thing that went wrong. Rehearse your project explanations aloud instead of only rereading them.

What to demonstrate

  • Hands-on knowledge of the primary stack, shown through your past projects
  • How clearly you explain your own work to a mixed audience
  • Collaboration and culture fit, which candidates report among the criteria for this role

How to prepare

  • Build two project deep dives on a single page each: context, your role, the architecture, a trade-off you chose, a defect or incident, and the measurable outcome.
  • Explain each project aloud in your own words, short version first and detailed version second, and note where you start guessing; those gaps are your study list.
  • Prepare one example of a code review you gave or received and how it changed the code.

Technical Evaluation

Candidates report a technical stage that mixes coding done live, discussion of architecture, and assessments tied to particular platforms, with HackerRank named as one example that some teams use. Prepare for both the coding side and the design side, out loud, in the language you intend to use.

What to demonstrate

  • Working code written live, including its edge cases
  • Architectural reasoning: scoping requirements, choosing components and stating trade-offs

How to prepare

  • Solve easy-to-medium problems in Java or Python in a plain editor, state the brute-force approach and its complexity first, and finish each with tests you write yourself.
  • Practise writing edge-case tests for a small string task: negative and large shift values, mixed case and non-letter characters.
  • Practise one design walkthrough per reported design topic, each ending with how you would handle failure, scaling and security.

Behavioral Evaluation

Candidates describe the last stage as a behavioral evaluation centred on past projects and the way you solve problems. The reported behavioral prompts are about translating business requirements with stakeholders, balancing deadlines against quality and technical debt, troubleshooting under pressure and explaining the outcome to non-technical colleagues, and mentoring junior developers. Prepare a small set of stories where you made the decision, and be able to retell each with a different emphasis.

What to demonstrate

  • Your contribution to past projects, as you describe it
  • How you approach and explain a problem when it is unfamiliar
  • Collaboration with product owners, peers and non-technical colleagues

How to prepare

  • Write four stories in situation, action, result form, one for each reported behavioral theme, and mark the sentence in each that says what you personally did.
  • Attach one number or observable outcome to every story, such as a defect rate, a delivery date kept or a review cycle shortened.
  • Rehearse the troubleshooting-under-pressure story with two audiences: an engineer, and a stakeholder who only needs impact and next steps.

Where candidates lose points

Answering the production memory leak question with 'restart it' or 'raise the heap size'

Give a sequence: confirm heap usage keeps growing after full collections, capture a heap dump (or enable dump on out-of-memory), inspect the largest retained objects in a tool such as Eclipse MAT, and check usual causes like unbounded caches, static collections, unremoved listeners, ThreadLocals and unclosed connections. Then say how you would verify the fix.

Describing a MongoDB aggregation without saying what happens to documents whose array is missing, null or empty

Say that $unwind drops those documents by default. With preserveNullAndEmptyArrays: true, a document whose array is empty or missing comes out without that field, and a document where the field is null keeps it as null. Put $match first so an index can be used, and say how $lookup followed by a preserving $unwind behaves like a left outer join.

Writing the Caesar Cipher or another string task for the happy path only

Handle shifts that are negative or larger than 26 with modulo arithmetic, preserve case, leave non-letters unchanged, and decide what null or empty input does. Say these cases before coding and cover them in unit tests.

Describing unit testing as 'I aim for high coverage' with no structure

Group tests by behaviour: normal flows, boundaries, invalid input, and each exception the method can throw, asserted by type and message. Say what you mock and what you keep real, and name the framework you use.

Telling project and behavioral stories in 'we' terms, with no decision or result of your own

For every story, write the sentence that starts with 'I decided' or 'I built', and add one measurable outcome. Keep the situation to two sentences and spend the rest on your reasoning.

Questions & practice

Can you walk through your approach to solving LeetCode easy-to-medium algorithmic coding problems?

Medium · Problem-Solving and Coding

Approach

  1. Clarify inputs and constraints, then work two or three examples by hand, including an edge case. The input size sets the target: with n around 10^5, an O(n^2) solution is too slow, and O(n log n) or O(n) is the goal.
  2. State the brute force and its complexity out loud, then name the pattern that improves it: a hash map for complement or frequency lookups, two pointers on sorted input, a sliding window for contiguous subarrays or substrings, binary search on a sorted or monotonic condition, BFS for shortest paths in unweighted graphs, a heap for top-k in O(n log k), and dynamic programming for overlapping subproblems.
  3. Write clean code with clear names and small helpers, then dry-run it on one example line by line before saying it is done.
  4. Give the time and space complexity of the final version, and check the edges: empty input, a single element, duplicates, negatives, and Java int overflow on sums or midpoints (use long, or lo + (hi - lo) / 2).

Follow-up

  • Can you reduce the extra space, and what does that cost in time?
  • How does the solution change if the input arrives as a stream?
  • Why is the greedy choice here correct, or show an input where it fails.

How do you structure comprehensive unit tests to cover both expected execution flows and exception scenarios?

Medium · Problem-Solving and Coding

Approach

  1. Structure every test as Arrange-Act-Assert, with one behaviour per test and a name that states the scenario and the expected result, so a failure explains itself.
  2. Choose cases by partition and boundary: a typical valid input, then null, empty, minimum, maximum and off-by-one values. In JUnit 5, @ParameterizedTest with @CsvSource or @MethodSource covers the boundary table without copy-pasted tests.
  3. For exception flows, use assertThrows, which returns the exception so its type and message can be asserted. Use Mockito's when(...).thenThrow(...) to simulate a failing dependency, and verify(...) or verifyNoInteractions to prove nothing was written or sent after the failure.
  4. Keep unit tests isolated and deterministic: mock external services, inject a java.time.Clock (Clock.fixed in tests) instead of calling now(), and move real database or HTTP checks into separate integration tests (for example with Testcontainers).
  5. Treat coverage as a signal, not the goal. JaCoCo line coverage shows code that ran, not what was asserted. Branch coverage and mutation testing (PIT) show whether the tests would actually catch a changed condition.

Follow-up

  • How do you test code that depends on the current date or time?
  • How would you test a private method?
  • A test passes locally but fails intermittently in CI. How do you track it down?

Canonicalise a request body into a stable idempotency fingerprint

Medium · parsing · canonicalisation · hashing

idempotency_key.request_fingerprint is a SHA-256 over the method, path and canonicalised body, and a retry whose fingerprint differs must be rejected with 422 rather than served the stored response. Write the canonicaliser. Bodies are JSON up to 256 KB nested at most 32 levels; clients vary key order, whitespace and unicode escaping, and some send 64-bit ids as JSON numbers. Produce a deterministic byte string such that semantically identical bodies match and any semantic difference does not. State your complexity and name two normalisations you refuse to perform.

Approach

  1. Parse once into a tree, then re-serialise under fixed rules: object keys sorted, array order preserved, one escaping convention, no insignificant whitespace. Parsing is O(n) and sorting keys is O(k log k) per object, so O(n log n) overall with O(depth) stack, and the 32-level cap is enforced during parsing because hostile nesting is how a canonicaliser becomes a stack overflow.
  2. Sort keys by their UTF-8 bytes and say why the obvious implementation is wrong in some runtimes: a default string comparison that orders by UTF-16 code units places surrogate pairs, meaning code points from U+10000 up, below U+E000 to U+FFFF, which is not UTF-8 byte order, so two services written in different languages disagree on the same document.
  3. Do not re-encode numbers through a double. IEEE-754 binary64 represents integers exactly only up to 2^53, so normalising a 19-digit id through a float changes it, and 1 against 1.0 cannot be reconciled without deciding whether they are the same value. Preserve the literal token, and require ids as strings at the API boundary if you want them comparable.
  4. Reject duplicate keys rather than picking one. JSON permits them and parsers disagree, most keeping the last, so any choice you make ties the fingerprint to a parser detail that the code handling the request does not necessarily share.

Follow-up

  • A client sends the same logical request with an extra field your API ignores. Same key, different fingerprint, so you return 422. Is that the right answer?
  • Where does the fingerprint get computed relative to request decompression and the body-size limit?

How do you approach writing an aggregate query in MongoDB, and what is the use case for operators like preserv

Medium · Technical and Domain Knowledge

How do you approach writing an aggregate query in MongoDB, and what is the use case for operators like preserveNullAndEmptyArrays?

Approach

  1. Write the pipeline as ordered stages: $match first, then $lookup or $unwind, then $group with accumulators such as $sum and $avg, then $sort, $project and $limit. On the source collection, only a leading $match or $sort (or $geoNear) can use an index, so filter before anything that reshapes documents.
  2. Explain $unwind: it emits one document per array element, and by default it drops documents where the field is missing, null or an empty array. With preserveNullAndEmptyArrays: true, a document whose array is empty or missing comes out without that field, and a document where the field is null keeps it as null. The stage then behaves like a LEFT JOIN instead of an INNER JOIN.
  3. Give an insurance use case I can reuse. Take policyholders joined to claims with $lookup. Unwinding the joined array without preserveNullAndEmptyArrays drops every policyholder with no claims, which skews a loss-ratio or claims-frequency report. Preserving them keeps the zero-claim policyholders in the denominator.
  4. Point out the counting trap. After $unwind, a $group count counts array elements, not parents. To count parents, group by the parent _id first, or use $size on the array without unwinding.
  5. Performance: put $match and $project before $unwind and $lookup to shrink documents early, index the $lookup foreignField (that index lives on the foreign collection), and know that a stage over the 100 MB memory limit needs allowDiskUse (or the server default on newer versions). Use explain() to check the plan.

Follow-up

  • How would you return each policyholder with their claim count, including policyholders with zero claims?
  • With includeArrayIndex set, what do you get for the documents kept by preserveNullAndEmptyArrays?
  • This aggregation got slow as the collection grew. What do you check in explain() first?

Write the update path that detects a concurrent edit

Medium · optimistic concurrency · transactional outbox · audit history

resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.

Approach

  1. One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
  2. Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
  3. State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
  4. Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.

Follow-up

  • A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
  • Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?

Can you explain your experience with API development and building enterprise integration services using MuleSo

Medium · Technical and Domain Knowledge

Can you explain your experience with API development and building enterprise integration services using MuleSoft or Java?

Approach

  1. Anchor the answer on one integration I built: the systems on each side, the contract (RAML or OpenAPI written before the code), and who consumed it. Without a concrete system the answer turns into a list of buzzwords.
  2. For MuleSoft, describe the API-led layering: system APIs wrap a backend, process APIs orchestrate, experience APIs shape data for a channel. Transforms go in DataWeave. For plain Java, the equivalent is Spring Boot controllers with DTOs, plus a @ControllerAdvice that maps exceptions to one error body.
  3. Error handling decides who sees a failure. In Mule, on-error-continue handles the error and returns success to the caller, while on-error-propagate handles it and then rethrows, so the caller sees a failure. In Java, separate retryable errors (timeouts, 503) from permanent ones (400, validation).
  4. Make writes safe to retry: an idempotency key or a natural business key the target checks, retries with exponential backoff and jitter only on transient errors, and a dead-letter queue for messages that keep failing.
  5. Security and operations: OAuth 2.0 client credentials between services, TLS, secrets kept out of config files (Mule secure properties or a secrets manager), and a correlation ID logged at every hop so one request can be traced end to end.

Follow-up

  • The downstream system timed out but may have applied the write. What happens when your caller retries?
  • How do you version this API without breaking consumers that have not upgraded?
  • A downstream dependency gets slow rather than failing. How do you keep it from exhausting your threads?

How do you ensure secure identity lifecycle management and access provisioning in enterprise applications?

Medium · Technical and Domain Knowledge

Approach

  1. Frame it as the joiner-mover-leaver lifecycle, driven by an authoritative source such as the HR system. A joiner gets birthright access from their role, a mover gets new access and loses the old, and a leaver is disabled across every target system promptly, not just in the directory.
  2. Grant access by least privilege through roles mapped to entitlements (RBAC). Handle anything outside a role through an access request with an approval workflow, and enforce separation-of-duties policies that block toxic combinations before they are provisioned.
  3. Keep the record honest. Regularly aggregate accounts from each target system and correlate them to identities so orphaned and unmanaged accounts surface. Run periodic access certifications where managers or app owners confirm or revoke each entitlement. In SailPoint IdentityIQ, these are the aggregation, correlation, lifecycle event, policy and certification features.
  4. On the application side, use standards instead of custom user stores: SAML or OIDC for single sign-on, SCIM for provisioning and deprovisioning, and OAuth 2.0 with short-lived tokens for APIs. On a leaver event, also revoke sessions and refresh tokens.
  5. Make every grant, approval and revocation auditable, with who, what, when and why recorded. In a regulated environment, being able to prove access was removed matters as much as removing it.

Follow-up

  • A mover keeps their old team's access for months. How does your design prevent that privilege creep?
  • A target application has no connector. How do you provision and deprovision it reliably?
  • An employee is terminated mid-session. What stops their existing tokens from still working?

How would you design a scalable microservices architecture using Spring Boot and cloud-native technologies on

Medium · System Design and Architecture

How would you design a scalable microservices architecture using Spring Boot and cloud-native technologies on AWS?

Approach

  1. Draw service boundaries along business capabilities, with each service owning its own data store. Shared databases between services couple their deployments and schemas, and that defeats the split.
  2. Lay out the AWS path. Traffic enters through API Gateway or an Application Load Balancer. Stateless Spring Boot containers run on ECS Fargate or EKS across several Availability Zones, with autoscaling on CPU or request count. Config comes from Spring profiles, and secrets from Secrets Manager or Parameter Store. Infrastructure is defined in Terraform.
  3. For communication, use synchronous REST only where the caller needs the answer now, with timeouts plus Resilience4j circuit breakers and bulkheads. Use asynchronous events (SQS/SNS or Kafka) for everything else, so a slow consumer does not block the producer.
  4. For consistency across services, avoid distributed transactions. Use a saga with compensating actions and a transactional outbox, so the database write and the event publish cannot diverge. In an insurance setting: a claim is approved in the claims service and the payments service must issue the payout. If the payout fails, the compensating action returns the claim to a pending-review state instead of leaving it approved but unpaid. Make consumers idempotent, because queues deliver at least once, so a replayed approval cannot pay twice.
  5. For operations, wire Actuator health and readiness endpoints into the load balancer health checks, export Micrometer metrics to CloudWatch, add distributed tracing (OpenTelemetry or X-Ray) with correlation IDs, and deploy with rolling or blue/green releases that roll back automatically when health checks fail.

Follow-up

  • A claim is approved in the claims service and a payout must be issued by the payments service. How do you keep the two consistent when the payout fails?
  • One downstream service slows to several seconds per call. How do you stop that cascading through the system?
  • When would you advise against splitting this into microservices at all?

Can you walk through how you integrate front-end applications built in Angular with backend RESTful services?

Medium · System Design and Architecture

Approach

  1. Put every backend call in an injectable Angular service that uses HttpClient with typed response interfaces, and keep the base URL in environment config. HttpClient returns cold Observables, so no request is sent until something subscribes.
  2. Use HttpInterceptors for cross-cutting concerns: attaching the Bearer token, adding a correlation ID, and central error handling (for example, a 401 triggers a token refresh or a redirect to login). Components then only handle their own success and error states.
  3. Pick RxJS operators for the behaviour you need. switchMap for search-as-you-type cancels the previous in-flight request. catchError turns failures into UI state. Retry only idempotent GETs, never POSTs that create records.
  4. Cover security and CORS. For an SPA, use OIDC with authorization code plus PKCE. Avoid long-lived tokens in localStorage because of XSS. With cookie-based sessions, Angular's XSRF support reads the XSRF-TOKEN cookie and sends X-XSRF-TOKEN on mutating requests. The backend must allow the SPA's origin, and a dev proxy avoids CORS during local development.
  5. On the Spring side, use @RestController endpoints with DTOs, @Valid request validation, a consistent error body (Spring's ProblemDetail follows RFC 7807), pagination for lists, and an OpenAPI spec the frontend team can generate clients from.

Follow-up

  • The access token expires while several requests are in flight. How do you refresh once without failing them all?
  • A user double-clicks Submit and two records get created. How do you fix that on both sides?
  • The browser shows a CORS error on a PUT but GETs work. What is happening?

What considerations do you make when designing CI/CD pipelines for automated build, test, and deployment proce

Medium · System Design and Architecture

What considerations do you make when designing CI/CD pipelines for automated build, test, and deployment processes?

Approach

  1. Build once and promote the same artifact. The pipeline produces one immutable artifact (a container image tagged with the commit SHA), and that exact image moves through test, staging and production, so what was tested is what ships.
  2. Order the tests for fast feedback. Unit tests and static analysis run on every commit, integration tests use real dependencies through Testcontainers, contract tests run between services, and a small end-to-end suite runs before release. Cache dependencies and run jobs in parallel to keep the pipeline quick.
  3. Add security and compliance gates: dependency (SCA) and container image scanning, SAST, secret scanning, and code-quality thresholds such as SonarQube. Pull secrets from a vault at deploy time instead of storing them in the repo. Record approvals for production so the release is auditable.
  4. Make deployments safe: rolling, blue/green or canary releases gated on health checks and error-rate metrics, with automatic rollback. Use backward-compatible database migrations (expand, then contract, through Flyway or Liquibase) so the previous version can still run after a migration.
  5. Treat infrastructure the same way: Terraform plan output reviewed in the pull request and applied by the pipeline, not by hand, so environments do not drift.

Follow-up

  • A flaky test fails one build in ten. What do you do about it?
  • A release needs a column rename. How do you ship it so rollback still works?
  • How would you add a compliance check to an existing pipeline without slowing every build?

How do you manage database interactions efficiently across both relational and NoSQL databases in a distribute

Medium · System Design and Architecture

How do you manage database interactions efficiently across both relational and NoSQL databases in a distributed system?

Approach

  1. Choose the store by access pattern. Relational databases suit data that needs transactions, constraints and ad hoc joins. A document or key-value store suits document-shaped records or very high-volume lookups by key. Say what each store in my design holds and why.
  2. On the relational side: pooled connections (HikariCP), with pool size times instance count kept under the database's connection limit; no N+1 queries in JPA (fetch joins or entity graphs); batched writes; indexes that match the actual WHERE and ORDER BY; and keyset pagination instead of large OFFSETs.
  3. On the NoSQL side, model around the queries. In MongoDB, decide embed vs reference and index the filter fields. In DynamoDB, choose a partition key with enough spread to avoid hot partitions, and know that queries not served by the key or an index fall back to scans.
  4. Across stores, there is no shared transaction. Use a transactional outbox or change data capture to publish changes, make consumers idempotent, and accept and document eventual consistency. Read replicas and caches add staleness too: use cache-aside with TTLs and invalidate on write.
  5. Name the failure modes: pool exhaustion under load, replica lag returning stale reads right after a write, and a write that succeeds in one store but fails in the other. For each one, say how I detect it (metrics, reconciliation jobs) and how I recover.

Follow-up

  • The relational write succeeds but the NoSQL update fails. How does the system end up consistent?
  • Under peak load, requests hang waiting for database connections. How do you diagnose and fix it?
  • A user updates a profile and immediately sees the old value. Where could that come from?

Write a function to implement a Caesar Cipher integration or similar string manipulation task.

Medium · Problem-Solving and Coding

Approach

  1. Clarify the spec first: shift letters only, preserve case, leave digits, spaces and punctuation unchanged, and confirm whether the key can be negative or larger than 26.
  2. Core logic: for a lowercase c, the output is (char)((c - 'a' + k) % 26 + 'a'), and the same with 'A' for uppercase. Normalise the key first with ((k % 26) + 26) % 26, because Java's % keeps the sign of the dividend, so a negative k would otherwise produce a negative index. In Python the % operator already returns a non-negative result for a positive modulus, so k % 26 is enough there.
  3. Check ranges with explicit 'a'..'z' and 'A'..'Z' comparisons rather than Character.isLetter, which also returns true for accented and non-Latin letters that the formula would corrupt. Build the output with a StringBuilder (or a char array): repeated String concatenation in a loop is quadratic.
  4. The reported wording says 'Caesar Cipher integration', and MuleSoft is part of this stack, so add one line on the same transform as a reusable DataWeave function called from a transform step in a Mule flow, with the key passed in as a parameter and an MUnit test around the edge cases.
  5. Complexity is O(n) time and O(n) space for the output. Decryption is the same function called with -k (or 26 - k), which is worth showing by reusing one method. Test the edges: empty string, null input (decide whether to throw or return null), k = 0, k = 26, a negative k, wrap-around at 'z' and 'Z', and mixed text with punctuation.

Follow-up

  • How would you decrypt a message without knowing the key?
  • Extend it to a Vigenère cipher with a keyword. What changes?
  • Write the unit tests you would ship with this function.

Given a set of requirements for a data transformation pipeline, how would you architect the data flow and hand

Medium · Problem-Solving and Coding

Given a set of requirements for a data transformation pipeline, how would you architect the data flow and handle edge cases?

Approach

  1. Pin down requirements first: batch or streaming, volume and latency targets, source and sink formats, who consumes the output, and what correct means (a reconciliation rule). The architecture follows from these answers.
  2. Lay out the flow: ingest, land the raw data unchanged (so it can be replayed), validate against a schema, transform, then load to the target. Each stage is a separate, restartable step with checkpoints.
  3. Handle bad data explicitly. Route malformed or rule-breaking records to a quarantine or dead-letter store with the reason attached, instead of failing the whole run or silently dropping them, and alert when the reject rate crosses a threshold.
  4. Make loads idempotent so reruns and duplicate deliveries are safe: upsert or merge on a natural key, or overwrite a whole partition (for example, one per date). Then reprocessing a day yields the same result.
  5. Cover time and schema edge cases: normalise timestamps to UTC, separate event time from processing time for late or out-of-order records, handle nulls and defaults deliberately, and decide how schema changes are handled (additive columns tolerated, breaking changes stop the run). Finish with reconciliation checks such as source vs target row counts and sums.

Follow-up

  • The source sends the same file twice. What happens in your pipeline?
  • How would you backfill a year of history without disrupting the daily run?
  • An upstream team adds a column and renames another. How does the pipeline react?

What strategies do you use to identify, troubleshoot, and resolve memory leaks in production applications?

Medium · Technical and Domain Knowledge

Approach

  1. First confirm it really is a leak. Look at heap after full GC: in a leak the old-generation baseline keeps rising, while a heap that is simply too small plateaus. Check GC logs and JVM metrics, not just process RSS or a single OutOfMemoryError.
  2. Capture evidence on one instance taken out of the load balancer: jcmd <pid> GC.heap_dump, or -XX:+HeapDumpOnOutOfMemoryError set in advance. A dump pauses the JVM and is roughly the size of the used heap. Take two dumps some time apart so growth can be compared.
  3. Analyse in Eclipse MAT. Use the dominator tree and retained size to find what holds the memory, then the path to GC roots to see why it is still reachable. Usual Java culprits: static maps or caches with no eviction, ThreadLocals in pooled threads that are never removed, listeners that are never deregistered, unclosed streams or connections, and classloader leaks after redeploys.
  4. If the heap is flat but RSS grows, the leak is off-heap. Check direct ByteBuffers, Metaspace and thread count, and turn on Native Memory Tracking (-XX:NativeMemoryTracking=summary, then jcmd VM.native_memory).
  5. Mitigate, then fix. Rolling restarts or more headroom buy time. The real fix is bounded caches (size and TTL), try-with-resources and ThreadLocal.remove() in finally blocks, plus a test that runs the code path in a loop and an alert on the post-GC heap baseline.

Follow-up

  • Heap after GC is flat but the container keeps getting OOM-killed. What do you look at next?
  • How would you reproduce a leak that only shows up after days of production traffic?
  • How do you tell a real leak from a cache that is just sized too large?

Can you describe a situation where you had to troubleshoot a complex technical issue under pressure and commun

Medium · Behavioral and Situational

Can you describe a situation where you had to troubleshoot a complex technical issue under pressure and communicate the resolution to non-technical team members?

Approach

  1. Pick a real incident where I personally drove the investigation, and open with the impact in plain terms: which users or business process were affected and what they could not do.
  2. Show the sequence. I mitigated first (rollback, feature flag, failover or scaling) to stop the damage, then reconstructed what had changed (deploys, config, traffic, a dependency), then narrowed down with metrics, logs and traces tied together by a correlation ID, testing one hypothesis at a time.
  3. Show the communication separately. I sent updates to non-technical stakeholders at a regular cadence, covering impact, workaround, current status and when the next update would come, in business language rather than stack traces. I also kept one channel as the single source of truth.
  4. Close with the root cause, the fix, and a measurable result (for example, error rate back to baseline, or no repeats since), plus the follow-up actions from a blameless review: an alert, a test or a runbook.
  5. The answer falls apart if the story is all jargon, if the fix came from someone else, or if it never says what the business heard and when.

Follow-up

  • How did you decide between rolling back and fixing forward?
  • What did you tell stakeholders before you knew the cause?
  • What changed afterwards so the same issue could not happen again?

Suggested practice checklist

The plan follows the four reported rounds and the reported question groups: stack and projects first, then integration and data, debugging and identity, coding, architecture, and finally behavioral stories.

Day 1 — Map the loop and your stack

  • Write the four reported rounds in order and one line on what each stage covers: Recruiter Screening, Virtual/Panel Interviews, Technical Evaluation, Behavioral Evaluation.
  • Mark each requirement and nice-to-have (Java or Python, Spring Boot, MuleSoft, SQL and NoSQL, CI/CD, AWS, Terraform, Docker, Kubernetes, Angular) as strong, working knowledge or unused.
  • Write the short career walkthrough you would give a recruiter, naming the matching projects.

Deliverable: One page with the loop map, the stack self-rating and the written career walkthrough.

Day 2 — Integration services and REST with Angular

  • Outline your answer on API development and enterprise integration services using a real project: authentication, error handling, retries, and how you tested it.
  • Sketch how an Angular front end talks to a REST backend: service layer, HTTP interceptors for auth and errors, CORS, and what the UI shows when a call fails.

Deliverable: A written outline for each of the two reported answers plus a working solution to the practice exercise.

Day 3 — MongoDB aggregation and mixed data stores

  • Write a small collection with a missing array, a null array and an empty array, then run an aggregation with $match, $unwind and $group both with and without preserveNullAndEmptyArrays to see the difference.
  • Outline how you would manage access to both a relational database and a NoSQL store in a distributed service: where transactions are needed, how you avoid cross-store inconsistency, and which indexes matter.

Deliverable: A saved aggregation with its output for each variant, a half-page answer on mixed data stores, and the finished practice exercise.

Day 4 — Memory leaks and identity lifecycle

  • Write your memory leak sequence for a production service: confirm growth, capture a heap dump, find retained objects, form a cause, fix, verify with a repeat run.
  • Write an outline of identity lifecycle management: joiner, mover and leaver events, provisioning and deprovisioning, entitlements, access reviews and audit evidence.
  • List the terms from the reported topic breakdown (SailPoint IdentityIQ, entitlement management) and write a plain definition of each in your own words.

Deliverable: A one-page debugging runbook and a one-page identity lifecycle outline with definitions.

Day 5 — Coding, tests and a data pipeline

  • Implement a Caesar Cipher in Java or Python with tests for negative and large shifts, mixed case, punctuation and empty input.
  • Solve three easy-to-medium problems, saying the brute-force approach and its complexity before the improved one.
  • Write unit tests for a method that can throw: normal flows, boundaries and each exception path.
  • Outline a data transformation pipeline from a requirements list: stages, validation, bad-record handling, idempotent reruns.

Deliverable: A tested cipher, three solved problems with complexity notes, a unit test class and a pipeline outline.

Day 6 — Architecture on AWS and CI/CD

  • Design a Spring Boot microservices system on AWS out loud: service boundaries, API gateway and authentication, data stores, messaging, observability, and failure handling.
  • Write a CI/CD pipeline from commit to production: build, unit tests, security and dependency checks, packaging, staged deployment, rollback.
  • Add where Terraform, Docker and Kubernetes would fit, and say which parts you have used yourself.

Deliverable: A diagram for the microservices design and a stage-by-stage pipeline outline, each with a trade-offs list.

Day 7 — Behavioral stories and a full rehearsal

  • Write the four reported behavioral stories in situation, action, result form and add one measurable outcome to each.
  • Rehearse the troubleshooting-under-pressure story for an engineer and then for a non-technical stakeholder.
  • Run the full sequence aloud: career walkthrough, one project deep dive, one design question, one coding task, one behavioral story.

Deliverable: Four written stories and a full recorded rehearsal with a list of the weakest moments.

Behavioral preparation for the AIG loop

Candidates describe the final stage as a conversation about past projects and how you solve problems. For a Software Engineer the reported prompts cover working with stakeholders to turn requirements into software, weighing deadlines against code quality and technical debt, troubleshooting under pressure and explaining the result to non-technical people, and mentoring other developers. Prepare stories in which you made the decisions and can state a result. Also prepare a project deep dive of your own: your specific contribution, the main challenge and how you resolved it.

  1. Can you describe a situation where you had to troubleshoot a complex technical issue under pressure and communicate the resolution to non-technical team members?

Tell me about a time when you had to collaborate with cross-functional stakeholders to translate complex busin

Medium · Behavioral and Situational

Tell me about a time when you had to collaborate with cross-functional stakeholders to translate complex business requirements into technical solutions.

Approach

  1. Choose a project where the request arrived in business language and had to become something buildable, such as a rule, a workflow or a report. Name the stakeholders by function (product owner, IT lead, another team) and say what each wanted.
  2. Spend most of the answer on how you closed the gap: clarifying questions, concrete examples and edge cases written down, acceptance criteria agreed before coding, a diagram or prototype that let non-engineers react to something real.
  3. Show one moment where the first interpretation was wrong or two stakeholders conflicted, and how you resolved it, for example by laying out options with cost and risk in plain language.
  4. Close with the result and how you confirmed you built what they meant: sign-off, a demo, a metric, or a defect that never occurred. The usual mistake is a story about receiving a spec, with no translation and no conflict.

Follow-up

  • What did the stakeholders misunderstand about the technical constraints, and how did you explain it?
  • How did you handle a requirement that changed after development had started?
  • What would you do differently to catch that misunderstanding earlier?

How do you handle tight deadlines and competing priorities while maintaining high code quality and addressing

Medium · Behavioral and Situational

How do you handle tight deadlines and competing priorities while maintaining high code quality and addressing technical debt?

Approach

  1. Pick a real moment where two things competed, such as a release date and a refactor, or two urgent requests from different owners. State the stakes of each in a sentence.
  2. Describe your prioritisation method: who owns the priority call, how you ranked by impact and risk, and what you negotiated. Strong answers negotiate scope or sequence, not the tests or review step.
  3. Say how you kept quality up under time pressure: tests on the riskiest paths first, a feature flag or staged rollout, a smaller reviewable change, and a short note of what was deliberately skipped.
  4. Make the technical debt explicit: a ticket with its cost and trigger, a place in the backlog, and what you paid down afterward. Finish with what shipped and what the shortcut cost. Avoid answers that rely on working nights or that claim there was no trade-off.

Follow-up

  • What would you have done if the product owner asked you to skip tests to hit the date?
  • How do you decide which technical debt is worth paying down now?
  • How did you tell stakeholders that something would slip?

How do you approach mentoring junior developers and contributing to a culture of knowledge-sharing within your

Medium · Behavioral and Situational

How do you approach mentoring junior developers and contributing to a culture of knowledge-sharing within your team?

Approach

  1. Anchor the answer in one specific person: where they started, what you worked on together and what they could do alone afterward. Abstract statements about being supportive carry little weight.
  2. Describe the methods you used: pairing on a real ticket, review comments that explain the reason behind a change, tasks that grew in difficulty, and walking through a production incident together instead of fixing it yourself.
  3. Cover knowledge-sharing beyond one person: a runbook, a short architecture note, a team session or a decision record, and evidence that others used it, such as fewer repeated questions.
  4. Be honest about cost and a miss: it took your own time, and something did not work at first, such as doing too much for the person. Say what you changed. The usual mistake is a story in which you solve the problem and the junior only watches.

Follow-up

  • How do you handle a junior developer who keeps repeating the same mistake?
  • How do you give review feedback to someone more senior than you?
  • How do you know whether the documentation you wrote is being used?