Interview guides · Advance Intelligence Group
Advance Intelligence Group Software Engineer Interview Guide
Advance Intelligence Group Software Engineer interview guide: 3 reported rounds, system design, testing and caching questions, plus a 7-day plan.
The 60-second brief
Advance Intelligence Group is described in candidate accounts as a fintech business whose systems handle financial transactions and data processing across several markets. A candidate review mentions exposure to financial technology and digital lending. The Software Engineer role is reported to cover backend services that run under high concurrency, plus mobile-first applications on some teams. The work described includes building and maintaining core services, working with product managers and data scientists to turn business requirements into technical specifications, taking part in code reviews and architecture discussions, and troubleshooting production issues to keep services available.
This guide is for Software Engineer candidates, mainly backend-leaning, preparing for the Advance Intelligence Group loop. The requirements candidates describe list a backend language such as Java, Go or Python, a solid grasp of distributed systems, and database design across SQL and NoSQL. Cloud (AWS or GCP), containers (Docker, Kubernetes) and fintech experience are listed as extras, and the typical background is 3-5+ years. The guide covers the three reported rounds, all nine reported questions (three on system design, three on coding practice and caching, three behavioral) and a seven-day plan.
Candidates report three rounds over roughly 3-5 weeks: Initial Contact, Technical Assessment and Deep-Dive Interviews. The reported emphasis is system design, testable code and clear communication about scope and team structure.
Focus areas
- Architecture (System Design)
- High-Load Systems
- Testing Strategy (Unit Testing)
Overview
The work candidates describe is backend engineering under load: services that stay correct while many requests hit them at once, in a business where the data is money. That shapes the reported questions. Three are design questions about a high-load fintech system serving mobile and web, consistency across microservices, and sharding or partitioning a financial platform. Three are engineering-practice questions about writing clean, testable code under time pressure, unit testing with mocks, and caching trade-offs for a mobile-first app. Three are behavioral. Prepare each group with its own method rather than one generic routine.
For the design questions, candidates report that a high-level diagram is not enough. Be ready to name the database you would pick and why, how you manage latency, and what happens when a dependency fails. Two further scenarios are reported: designing a payment gateway that handles 10,000 transactions per second, and ensuring zero data loss during a service deployment. Practise the mechanisms behind them: idempotency keys, a transactional outbox, saga-style compensation, partition keys and their query costs, graceful shutdown, and backward-compatible schema changes. After each design choice, say which alternative you rejected and why. Candidate accounts name this as a recurring habit of strong answers.
For the coding and testing side, candidates report that testing methodology comes up repeatedly. The reported scenarios are refactoring a function for performance and readability, and implementing a feature that has to handle edge cases in user input. Choose one of Java, Go or Python, and practise writing a small function together with its tests, using a fake or mock for the outside dependency and justifying the time and space complexity. In a money context, show that you know not to use binary floating point for amounts.
The people side matters too. Candidate accounts advise stating early whether you prefer to stay an individual contributor or move toward managing a team, because requirements are reported to shift with internal restructuring. Some candidates also report uneven detail from recruiters on team structure and reporting lines, so prepare targeted questions about team scope and your potential manager's background.
The Advance Intelligence Group interview process
Candidates describe three stages, from a recruiter conversation to a coding assessment to architecture-focused discussions. The descriptions below are what candidates report, not a published process, and the pace is said to vary with each team's hiring urgency.
Initial Contact
Candidates describe this as the first outreach from a recruiter, who discusses the opportunity and collects information about you. Candidate accounts add two practical points: be ready to say whether you prefer individual contribution or team management, and ask pointed questions about team scope and your potential manager, since some candidates found recruiters inconsistent on reporting lines. Treat it as a serious conversation about your background and what you want.
What to demonstrate
- Advice: be able to summarise your backend and high-load experience clearly
- Advice: be ready to state your preference between individual contribution and managing a team
- Advice: check that what you want from the role and team matches what is described to you
How to prepare
- Write a brief summary of your most relevant system: its language, the load it carried, its datastore and your part in it, using only numbers you can defend.
- Decide your answer on individual contribution versus managing a team, and say it in one plain sentence.
- Write questions for the recruiter about team size, the scope of the team's work, and your potential manager's background.
- Rehearse a motivation answer for why you want to move into, or stay in, a fast-scaling company, with one concrete example from your own career.
Technical Assessment
Candidates describe this stage as an evaluation of technical skills through coding challenges or assessments. The reported coding themes are clean, efficient and testable code, unit testing with mocked dependencies, justifying time and space complexity, and writing code other engineers can inherit. Two example scenarios are reported: "Refactor this function to improve performance and readability." and "Implement a feature that requires handling edge cases in user input." The format of the assessment is not specified, so prepare to write working, tested code in your chosen language.
What to demonstrate
- Working code that handles edge cases in user input
- Choice of algorithm and data structure, justified with time and space complexity
- Unit tests and the way dependencies are mocked
- Readability and maintainability of the result
How to prepare
- Pick one reported backend language (Java, Go or Python) and write a small amount-and-currency validation function with parametrised or table-driven tests, including empty, negative, over-precise and duplicate inputs.
- Store money as integer minor units or a decimal type in your examples, and be ready to say why a float is wrong.
- Write a test that fakes a failing or slow outside dependency, and explain when you use a stub, a fake or a strict mock.
- Take a tangled function from your own code, refactor it for speed and readability, and write the complexity before and after.
Deep-Dive Interviews
Candidates describe this round as in-depth discussions on architecture and problem-solving. Reported example scenarios include "Design a payment gateway that handles 10,000 transactions per second." and "How do you ensure zero data loss during a service deployment?" Candidate accounts say strong answers go beyond a diagram into database selection, latency and failure handling, and always name the alternative that was rejected.
What to demonstrate
- Database selection, latency management and failure handling inside a design
- Handling of traffic spikes and the trade-offs of each choice under high load
- Data integrity when a transaction spans several services
- Problem-solving ability
How to prepare
- Work the payment gateway scenario end to end: estimate peak load, choose a partition key, give every payment an idempotency key, and say what you do when a call times out.
- Write a one-page comparison of a local transaction, two-phase commit, saga compensation and a transactional outbox, with the failure each one leaves open.
- Practise the zero-data-loss deployment answer: draining in-flight requests, acknowledged durable queues, idempotent consumers, and expand-then-contract schema changes.
- Say aloud, for every component you add, the alternative you rejected and the reason.
Where candidates lose points
Drawing a boxes-and-arrows diagram for the payment or mobile-and-web system and stopping there
For each box, name the datastore and why, the expected load, and what happens when it is down. Candidates report that database selection, latency and failure handling are what separate strong design answers from diagrams. Practise saying "if this fails, the user sees X and the data is Y" for every component.
Answering the microservices consistency question with "use transactions" and no mechanism
A single transaction does not span services. Name the options and what each leaves open: two-phase commit and its blocking, saga compensation and its visible intermediate states, a transactional outbox with idempotent consumers, and reconciliation as a backstop. Tie the choice to money: which state is allowed to be stale and which is not.
Naming a shard key or cache without saying what it makes expensive
State the cost of every choice. A shard key on account id makes cross-account queries and rebalancing costly. A TTL cache on a mobile feed is fine, while the same cache on a balance after a transfer shows wrong data. Pair every pick with the alternative you rejected.
Submitting code in the coding stage with no tests, or with mocks that replace the logic under test
Write the test cases before or alongside the function, covering the edge cases in user input. Mock only the outside dependency, add a test where it fails or times out, and be ready to explain stub versus fake versus mock. Candidates report that testing approach is a recurring theme.
Leaving the role and team unclear and giving a vague answer on individual contribution versus managing a team
Decide your preference before the recruiter conversation and say it plainly. Ask about team size, scope and your potential manager's background, since candidates report uneven recruiter detail on reporting lines, and take notes so later rounds can build on what you were told.
Questions & practice
Can you walk through your process for writing clean, testable code under time constraints?
Medium · Coding & Technical Implementation
Approach
- Restate the task and pin the input contract out loud, then write three or four concrete examples before any code: the normal case, an empty input, a boundary value and an invalid input. Those examples become the first tests.
- Keep the core logic pure. Pass I/O and nondeterminism (database access, HTTP clients, the current time, random or id generators) in as parameters or constructor dependencies, so the logic can be tested with plain inputs and few or no mocks.
- Get a correct, simple version working first and run it against the examples. Only then refactor names and extract small functions, and only then optimise, stating the time and space complexity of each version and why the change is worth it.
- Make domain edge cases explicit in code: represent money in integer minor units or a decimal type, never binary floating point; make rounding rules explicit; validate inputs at the boundary and fail with clear errors rather than silently.
- Under pressure, use table-driven or parameterised tests so adding a case is one line, assert on outputs rather than internals, and finish by stating what you would add with more time (more failure-path tests, logging, input validation) instead of leaving it unsaid.
Follow-up
- If you had half the time, what would you cut first, and what would you refuse to cut?
- How would you test a function whose result depends on the current date or time?
- Here is a long function that mixes parsing, business rules and a database call. How would you refactor it for readability and testability?
Explain the trade-offs between different caching strategies for a mobile-first application.
Medium · Coding & Technical Implementation
Approach
- Name the layers first: on-device (HTTP cache, plus a local store such as SQLite, Room or Core Data), CDN or edge for static and public responses, and a server-side cache such as Redis in front of the database. Each layer has its own staleness and invalidation story.
- Compare the server-side patterns. Cache-aside is simple and caches only what is read, but data stays stale until TTL or explicit invalidation and every miss pays a round trip. Read-through moves that logic into the cache layer. Write-through narrows the staleness window at the cost of write latency, but does not guarantee consistency: concurrent writers can land in a different order in cache and database, and a failed cache write leaves them out of step. Safeguards are versioned writes or delete-on-write. Write-behind gives fast writes but can lose data on a crash, which rules it out for anything financial.
- For HTTP between app and server: Cache-Control max-age for freshness, ETag with If-None-Match so unchanged data returns 304 Not Modified and saves bandwidth on mobile networks, and stale-while-revalidate to show cached content instantly while refreshing in the background.
- Mobile-specific trade-offs: offline-first screens show cached data with a last-updated time, but money-moving decisions (available balance, limits) must be confirmed by the server, never from the device cache. Encrypt sensitive cached data at rest, clear it on logout, and invalidate through push messages or version numbers in responses.
- Failure modes: a stampede when a hot key expires (fix with request coalescing or a short lock, plus TTL jitter so keys do not expire together), unbounded growth (LRU or size-capped eviction), and stale shapes after a deploy (version the cache keys).
Follow-up
- How do you invalidate a value that is cached on millions of devices?
- Which data would you never cache on the device, and why?
- A popular key expires and the database is flooded with identical queries. How do you prevent that?
Describe a situation where you had to lead a technical project despite ambiguous requirements.
Medium · Behavioral & Leadership
Approach
- Choose a story where you set the direction yourself, not one where you carried out someone else's plan. A fitting setting for this company is a lending or payments feature with unclear requirements across several markets, or scope that changed after a team reorganisation. Keep the situation to two or three sentences: what was unclear (goal, scope, owner or success metric) and why waiting for clarity was not an option.
- Spend most of the answer on how you reduced the ambiguity: listing the unknowns, writing a one-page outline of assumptions, scope and explicit non-goals, getting the key stakeholders to confirm or correct it, and keeping a decision log as answers came in.
- Show how you de-risked delivery: a short spike or prototype on the riskiest assumption, a smallest-useful first slice shipped early, and checkpoints where requirements could change without wasting work. Say how you split the work across the team and kept everyone aligned when scope moved.
- Close with a measurable result and an honest reflection: an assumption that proved wrong, how you found out, and what you do differently now. Use 'I' for your own decisions so your contribution is visible.
- The mistakes that sink this answer: blaming stakeholders for unclear requirements, a story where you simply waited until someone else decided, or an ending with no outcome or lesson.
Follow-up
- Which of your assumptions turned out to be wrong, and how did you find out?
- How did you decide you had clarified enough and could start building?
- Requirements changed after the team had started. How did you handle the work already done?
Find version gaps and relay lag with window functions
Medium · window functions · event tables · frame semantics
outbox_event holds event_id, aggregate_type, aggregate_id, aggregate_version, event_type, payload, status ('pending','published','dead'), attempts, created_at, published_at. A projection is missing rows and you must decide whether the relay skipped events or the consumer dropped them. Write three queries over the last seven days: one listing every aggregate_id whose published aggregate_version sequence has a hole, one giving per-day counts with a running total, and one returning the newest published event per aggregate. For each, say where the window function is evaluated relative to WHERE and LIMIT. PostgreSQL 16.
Approach
- Gaps: compute lead(aggregate_version) OVER (PARTITION BY aggregate_id ORDER BY aggregate_version) in a subquery, then filter next_version <> aggregate_version + 1 in the outer query. Window functions are evaluated after WHERE, GROUP BY and HAVING and before the outer ORDER BY and LIMIT, so the predicate cannot sit in the same WHERE clause and PostgreSQL 16 has no QUALIFY.
- Say what the seven-day filter does to the answer: it truncates every partition, so the first row per aggregate has no predecessor inside the window and a hole spanning the boundary is invisible. Widen the window, or join to resource.version as the authority for the true maximum.
- Running total: SELECT date_trunc('day', created_at) AS d, count() AS n, sum(count()) OVER (ORDER BY date_trunc('day', created_at) ROWS UNBOUNDED PRECEDING). An aggregate inside a window call is legal because grouping runs before windowing. The grouping key is unique per row here so ROWS and RANGE agree, but write the frame anyway — over ungrouped rows with tied timestamps the default RANGE frame pulls in every peer row and the total jumps.
- Newest per aggregate: DISTINCT ON (aggregate_id) ... ORDER BY aggregate_id, aggregate_version DESC is the cheap PostgreSQL-only form when an index matches that order; row_number() OVER (PARTITION BY aggregate_id ORDER BY aggregate_version DESC) = 1 is the portable form and needs a subquery for the same evaluation-order reason as the gap query.
Follow-up
- Relay failover redelivers events. Does a duplicate break the gap query, and how would you detect one from this table alone?
- Turn the gap check into a continuous monitor rather than a query someone runs after an incident. What does it watch?
Explain why the owner filter ignores the listing index
Medium · composite index · query plans · sort elimination
The only index on resource is (tenant_id, status, updated_at DESC, resource_id DESC). A new endpoint returns one user's resources across all statuses, newest created first: WHERE tenant_id = $1 AND owner_user_id = $2 ORDER BY created_at DESC LIMIT 20. On a tenant with 2M rows it takes 900 ms and EXPLAIN shows a sort above a large scan. Explain precisely why the existing index cannot serve it, give the index that can, and state which of these the new index still will not help: owner_user_id alone across tenants; the same query ordered by updated_at. PostgreSQL 16.
Approach
- Separate the two jobs an index does. For filtering, a composite btree is seekable only on a left prefix, so with no predicate on status the scan can at best range over tenant_id and test owner_user_id per row; PostgreSQL 16 has no btree skip scan to jump the unconstrained column.
- For ordering, the index is sorted by (status, updated_at) within a tenant and not by created_at, so the LIMIT cannot stop early: every matching row is read and then sorted. That is the 'Sort Method: top-N heapsort' line, and it is why the plan reads 2M rows to answer with 20.
- Derive the replacement from the access path — equality, equality, then the ordering column: CREATE INDEX CONCURRENTLY ON resource (tenant_id, owner_user_id, created_at DESC). The scan seeks to the (tenant, owner) range and walks 20 entries in order, so the Sort node disappears along with the row-read.
- Treat INCLUDE (title, status) as conditional, not free. An index-only scan still visits the heap for any row whose page is not marked all-visible, so on a table taking 1.2k writes/second the win depends on autovacuum keeping the visibility map current, and the wider index costs more on every insert.
Follow-up
- 90% of rows are status='active'. Would a partial index WHERE status = 'active' change your answer, and for which of the three queries?
- A dashboard runs this for 40 owners in one page load. What changes about the design?
How would you design a high-load fintech system capable of supporting both mobile and web traffic?
Medium · System Design & Architecture
Approach
- Pin the scope before drawing anything: which flows matter (balance reads, transfers or repayments, onboarding), the read/write ratio, peak requests per second, and which calls move money. Keep the money path separate from content and profile reads, because they need different guarantees.
- Edge and API layer: a CDN for static assets, an API gateway that handles auth (short-lived access tokens plus refresh tokens), per-user and per-device rate limiting (token bucket), and a backend-for-frontend per client, so mobile gets compact payloads. Version the API, because old app versions stay installed long after a release.
- Write path: stateless services behind a load balancer, with a relational ledger using ACID transactions and double-entry rows. Every money-moving request carries a client-generated idempotency key stored under a unique constraint, so a mobile retry on a flaky network cannot charge twice.
- Async and read paths: use a transactional outbox plus a message queue for notifications, analytics and other non-blocking work. Serve reads from replicas and a Redis cache, but give a user read-your-writes on their own balance right after a transfer (read from the primary or pass a version token).
- Failure handling: timeouts, retries with backoff and circuit breakers on third-party calls (payment providers, bureaus), backpressure and queue-based load levelling for spikes, and partitioning by user or account id once one primary saturates. Name the metrics you would watch: p99 latency, error rate, queue lag.
Follow-up
- A payment provider call times out. How do you know whether the charge happened, and what does the client see?
- Traffic spikes tenfold for a few hours. Which component saturates first, and what do you do about it?
- How do you ship a breaking API change while older mobile app versions are still in use?
What strategies would you implement to ensure data consistency in a distributed microservices environment?
Medium · System Design & Architecture
Approach
- Start by sorting invariants. Anything that must be atomic, such as a ledger balance and its entries, stays inside one service and one local database transaction. Cross-service state can be eventually consistent if you say how and when it converges.
- Avoid the dual-write bug, where the DB commit succeeds but the event publish fails, with a transactional outbox: write the business row and an outbox row in the same transaction, then publish them with a poller or change data capture (for example Debezium).
- For workflows that span services, use a saga: a sequence of local transactions, each with a compensating action (issue a refund or a reversal entry, never delete history). Compare orchestration (one coordinator, easy to trace) with choreography (services reacting to events, looser coupling but harder to follow). Explain why you avoid 2PC/XA: a blocking coordinator, locks held across services, and weak broker support.
- Brokers deliver at least once, so consumers must be idempotent. Record processed message ids in a dedupe table inside the same transaction as the side effect. Partition by aggregate id (for example a Kafka partition key) to keep per-entity ordering, and use optimistic concurrency (a version column with compare-and-set) so a stale update cannot overwrite a newer one.
- Back it with detection: reconciliation jobs that compare internal ledgers against provider statements and against each other, alerts on outbox lag, and a dead-letter queue with a replay path.
Follow-up
- A compensating step itself fails halfway through a saga. What state is the system in, and how does it recover?
- Two events for the same account arrive out of order. How do you stop the older one from overwriting the newer state?
- Why not wrap the whole workflow in a distributed transaction?
How do you handle database sharding and partitioning for a high-traffic financial platform?
Medium · System Design & Architecture
Approach
- Use cheaper options first and say so: indexes, query fixes, read replicas, vertical scaling, then table partitioning inside one instance. For example, Postgres declarative range partitioning on created_at for transaction history gives partition pruning on date-bounded queries and lets you archive old data by detaching a partition.
- Pick the shard key from the dominant access pattern. A user or account id keeps one customer's balance and transactions on one shard, so most reads and writes stay single-shard. Name the cost: a transfer between two users can cross shards, and queries by merchant or by date across all users become scatter-gather.
- Compare strategies. Hash sharding spreads load evenly but loses range scans. Range sharding keeps range scans but creates a hot shard when the key is monotonic (timestamps, sequential ids). A directory/lookup service is the most flexible but adds a hop. Map many logical buckets (say 1024) onto fewer physical nodes, so rebalancing moves buckets instead of rehashing every row.
- Handle cross-shard concerns explicitly: globally unique ids (Snowflake-style or UUIDv7) instead of per-database auto-increment, cross-shard transfers as a saga with pending ledger entries and an outbox, and reporting from a replicated analytics store rather than live fan-out queries.
- Resharding without downtime: copy a bucket to its new node with a backfill plus CDC catch-up (or dual writes), verify with row counts and checksums, flip the routing entry, then clean up. Also plan for hot keys, such as one very large merchant account, which may need its own shard or write buffering.
Follow-up
- One merchant account generates a large share of all writes and its shard is hot. What are your options?
- Finance needs a daily report across every user. How do you produce it without hammering the shards?
- Walk through adding a new shard while the platform keeps taking writes.
How do you integrate unit testing and mocking into your development workflow?
Medium · Coding & Technical Implementation
Approach
- Lay out the test pyramid you work to: many fast unit tests on business logic, fewer integration tests against real dependencies (a real database in a container, for example with Testcontainers), contract tests at service boundaries, and a small number of end-to-end tests.
- Name the test doubles correctly and say when you use each: a stub returns canned answers, a mock verifies interactions, a fake is a working lightweight implementation (an in-memory repository), and a spy records calls on a real object. Prefer fakes and stubs for state, and use mocks only when the interaction itself is the behaviour (a payment request sent exactly once).
- Mock at boundaries you own: wrap third-party SDKs (payment gateway, SMS, credit bureau) behind your own adapter interface and substitute that interface, rather than mocking library types or value objects. Use constructor injection, and inject a clock and an id generator for deterministic tests.
- Explain the risk of over-mocking: tests that mirror the implementation break on every refactor and stay green while the real integration is broken. Counter it with outcome-based assertions, integration tests for the adapters, and consumer-driven contract tests (for example Pact) so mocks match the real service.
- Fit it into your workflow: write tests alongside or before the code, cover failure paths (timeouts, retries, duplicate requests, partial failures), run them in CI on every pull request, and treat coverage as a signal, not a target. In Python, patch the name where it is looked up, not where it is defined; in Java, Mockito; in Go, small interfaces with hand-written fakes.
Follow-up
- Give an example of a mock that gave you false confidence. What test would have caught the real bug?
- How do you test retry-with-backoff logic without making the test suite slow?
- How would you test code that calls an external payment API that has no sandbox?
Every query on one table stalls for forty seconds mid-deploy
Medium · lock contention · ddl · migrations
During a release on PostgreSQL, every query touching resource times out for about 40 seconds and then recovers with no intervention. The release ran one migration, ALTER TABLE resource ADD COLUMN archived_reason TEXT, and the migration log shows it completing in 6 ms. Unrelated tables showed no change in error rate. Explain how a 6 ms statement caused a 40-second stall, give the ordered checks you would run on a live system to confirm it, and give the migration procedure that prevents a repeat.
Approach
- Separate the statement's duration from the lock's duration. ADD COLUMN with no default is a catalogue-only change and genuinely runs in milliseconds, but it requires ACCESS EXCLUSIVE, and it cannot acquire that until every transaction already touching the table has finished.
- Account for the queueing, which is the part that surprises people. A lock request that is waiting blocks later requests for conflicting modes behind it rather than letting them overtake, so one long-open transaction holds the DDL and the DDL holds all the traffic. The stall length is set by the longest open transaction, not by the size of the change.
- Confirm on a live system in this order: pg_stat_activity for that table ordered by xact_start, looking for the oldest transaction and specifically for state = idle in transaction; then pg_locks where granted = false to find the waiter; then join them on pid to name blocker and blocked. pg_blocking_pids() does that join for you and is the fastest single call.
- Prevent rather than merely time it better. Set lock_timeout to a second or two on the migration session so the DDL abandons the queue after a bounded wait and is retried, instead of holding it for as long as the oldest transaction lives. Be exact about what that buys: queries arriving during the wait still queue behind the pending ACCESS EXCLUSIVE request, so each attempt costs them up to one lock_timeout of added latency. The outage goes from 40 seconds to about one second per attempt, not to zero. Also run migrations away from deploy-time peaks, and put a statement timeout and an idle-in-transaction timeout on the analytics role that opens the long transactions.
Follow-up
- The same release also wants NOT NULL on that column. What is the sequence that gets there without a long lock?
- Your lock_timeout retry fails ten times in a row because the analytics transaction is always open. What do you change?
Suggested practice checklist
Seven days built around the three reported rounds and the nine reported questions: one day for the loop and the recruiter conversation, three for design and caching, one for tested code, one for behavioral stories and one for a full rehearsal.
Day 1 — Map the loop and prepare the recruiter conversation
- Write the three reported rounds in order (Initial Contact, Technical Assessment, Deep-Dive Interviews) and beside each the format reported for it: recruiter outreach, coding challenges, architecture and problem-solving discussions.
- List the stack the role names (Java, Go or Python; SQL and NoSQL; AWS or GCP; Docker and Kubernetes) and mark each item you can discuss from real work.
- Write your answer on why you want to move into, or stay in, a fast-scaling company, and one plain sentence on individual contribution versus managing a team.
Deliverable: A one-page loop map, a marked stack list, a written motivation answer and a one-sentence statement of your individual-contributor or team-management preference.
Day 2 — Design a high-load fintech system for mobile and web
- Design the system for mobile and web traffic: clients, edge or gateway, stateless services, datastore, cache and queue. Draw the read path and the write path separately and estimate peak requests with numbers you choose.
- Work the scenario "Design a payment gateway that handles 10,000 transactions per second.": partition key, an idempotency key per payment, an append-only record of payment states, and the behaviour on timeout.
- List what fails first when traffic multiplies, and the response (rate limits, queueing, shedding load, degraded reads).
Deliverable: A diagram and half-page walkthrough of the mobile-and-web design, plus a written payment gateway design that states its idempotency and timeout behaviour.
Day 3 — Consistency, sharding and safe deployments
- Build a table comparing a local transaction, two-phase commit, saga compensation and a transactional outbox, with the failure each leaves open.
- Choose a shard key for account and transaction data, write which queries it makes expensive, how you rebalance, and how partitioning by time differs from sharding by key.
- Answer "How do you ensure zero data loss during a service deployment?" using graceful shutdown, draining, acknowledged durable queues and expand-then-contract migrations.
Deliverable: A consistency-mechanism table, a shard-key note with its query costs, a written deployment answer, and your notes from the two practice items.
Day 4 — Caching trade-offs for a mobile-first app
- Compare cache-aside, read-through, write-through and write-behind on consistency, failure mode and cost, and add TTL versus explicit invalidation and stampede control (request coalescing, jittered expiry).
- Add the device layer: HTTP caching with Cache-Control and ETag, an on-device cache for offline reads, and stale-while-revalidate.
- Decide screen by screen what may be stale (a content feed) and what must not be (a balance right after a transfer), and pick an eviction policy and size limit for the on-device cache.
Deliverable: A one-page caching decision table with a per-screen choice and the reason for each.
Day 5 — Write clean, tested code
- In your chosen language (Java, Go or Python), implement a function that validates an amount and currency from user input: handle empty, negative, over-precise and duplicate submissions, and keep money in integer minor units or a decimal type.
- Write unit tests with a fake or mock for the outside dependency, including one case where it fails or times out, and note why you chose a stub, fake or mock in each.
- Refactor one slow or tangled function of your own for performance and readability and write its complexity before and after.
Deliverable: A working function with its tests, a note on each test double you chose, and a before-and-after refactor with the complexity written down.
Day 6 — Behavioral stories and recruiter questions
- Write outlines for three stories: leading a technical project through ambiguous requirements, managing expectations with a non-engineering stakeholder, and a design you argued against, lost and then committed to.
- Say each story aloud, spending two sentences on the situation and the rest on your reasoning, the decision you made and the result you can verify.
Deliverable: Three story outlines, a spoken run of each, and a list of questions about team scope and reporting line.
Day 7 — Full rehearsal
- Give a spoken design answer to one of the three reported design questions, naming the rejected alternative for every major choice.
- Complete a fresh coding task: list the test cases first, then write the function and tests.
- Give a one-sentence opening answer to each of the seven reported design, coding and project-leadership questions, then redo the weakest two in full. Rerun the two stakeholder and motivation stories from day 6 aloud.
Deliverable: A recorded design walkthrough, a tested solution to a fresh task, seven opening lines with the two weakest answers redone, and a spoken run of the day 6 stories.
Behavioural preparation
The reported behavioral questions cover leading a technical project through ambiguous requirements, setting expectations with stakeholders who are not engineers, and your reason for joining or staying in a fast-scaling company. Candidate accounts also stress adaptability and composed communication when team structure or reporting lines come up. Prepare stories where you made the decision, state the stakes in two sentences, and spend the rest on your reasoning and the checkable result.
- Describe a situation where you had to lead a technical project despite ambiguous requirements.
- Tell me about a design decision you argued against, lost, and then committed to anyway. What did you do after the decision was made?
- Describe a production issue you troubleshot: how you found the cause, what you fixed, and what you changed so it would not recur.
- Tell me about a time team priorities or structure changed mid-project and how you adjusted your work.
How do you manage expectations when reporting to stakeholders with non-engineering backgrounds?
Medium · Behavioral & Leadership
Approach
- Choose a story where a non-engineering stakeholder (a product manager, an operations or finance owner) needed a date, a scope decision or a risk call from you. The role is described as working with product managers and data scientists, so a partner like that fits. Say who they were and what they had to decide.
- Show the translation. Restate the technical constraint in their terms: for example, that the schema change cannot share a release with the campaign launch because a rollback would mean reconciling duplicate balances by hand. Give estimates as a range with the assumptions behind it, not as one date.
- Describe the routine you set up: a short written update with status, risk and the decision you need, sent on a regular schedule. Show how early you flagged slippage and that you brought options (cut scope, move the date, add a person), not just the problem.
- Close with an outcome that can be checked: what shipped, what the stakeholder changed because of your report, and one thing you would do differently. The mistake that sinks this answer is a story where you agreed to everything and the date slipped quietly, or one that blames the stakeholder for not understanding.
Follow-up
- What did you do when the stakeholder pushed back on your estimate?
- How did you confirm they understood the risk and were not simply agreeing?
- Tell me about a time you had to deliver a date you did not agree with.
Why are you interested in transitioning into or maintaining your role within a fast-scaling company like Advan
Medium · Behavioral & Leadership
Why are you interested in transitioning into or maintaining your role within a fast-scaling company like Advance Intelligence Group?
Approach
- Structure the answer in three parts: what you have built that fits this work, what draws you to this particular work, and what you want the next role to give you. For the middle part, the role is described around backend services under high concurrency, distributed systems and fintech, so point to a system of yours that carried real load or handled money-like data.
- Connect "fast-scaling" to evidence from your career, not to a liking for pace: a service you took through a traffic jump, a queue or schema you had to rework as volume grew, an incident that changed how you design. Say what each taught you.
- The question covers both moving in and staying in a role. State which applies to you and give an honest reason, framed around what you are heading toward and not around what you dislike at your current employer.
- If the fintech and digital lending exposure that candidate reviews mention is part of your interest, explain it in engineering terms such as transaction consistency, idempotent retries and reconciliation, not as admiration for the company.
- Be ready to say whether you want to remain an individual contributor or move toward managing a team. Candidate accounts advise settling this early, since requirements are reported to change with internal restructuring.
Follow-up
- Do you see yourself as an individual contributor or managing a team in two years?
- What would you want to know about the team's scope and reporting line before accepting?
- How do you keep delivering when priorities or team structure change mid-project?
Argue against a design, lose, and commit anyway
Medium · disagreement · service boundaries · decision records
Describe a design you argued against and lost. State the failure you predicted as a named mechanism, not a feeling about complexity: two services that would need one transaction, a projection with no rebuild path, a write path with no idempotency key. Say what evidence you brought, what the decision maker weighed instead, and what you did after the decision was made: what you instrumented, what you wrote down, and whether the prediction came true. Five minutes.
Approach
- State the prediction in falsifiable form up front: the mechanism, the condition that triggers it, and the observable outcome. A prediction that cannot be checked also cannot be credited to you later.
- Show the evidence you had at the time and label each piece honestly as measured, analogous, or intuition. Keeping the intuition is fine; disguising it as data is the thing that erodes your standing in the next argument.
- Represent the opposing case at full strength, including the constraint you did not control: a fixed date, a team boundary, or the fact that the decision was cheap to reverse and yours was not.
- Make disagree-and-commit concrete. Name the artefact you left behind so the prediction could be settled without you: the alert and its threshold, the counter on the dashboard, the decision note that recorded the trade-off and the condition that would revisit it.
Follow-up
- What threshold on that alert would have proved you right, and did anyone ever look at it?
- If the same proposal arrived tomorrow with the same deadline, would you argue it the same way?