Interview guides · Accern
Accern Software Engineer Interview Guide
Accern Software Engineer interview guide: four reported rounds, GraphQL, TypeScript, React and SQL questions, system design, and a 7-day prep plan.
The 60-second brief
Accern builds a no-code AI platform for financial service enterprises. Candidates describe it as a product that helps clients automate AI workflows, cut costs and gain insight into risk and investment decisions. The Software Engineer role sits on the product side of that platform: building web user interfaces, writing new GraphQL APIs, and maintaining the integrations that connect those APIs to backend systems. Candidates also report that the surrounding work touches natural language processing and predictive modeling.
This guide is for engineers preparing for Accern's Software Engineer loop. Candidates describe the stack as TypeScript, Node, GraphQL, SQL, React and Apollo GraphQL, with GitHub, Confluence, Jira and ElasticSearch as tools to be familiar with, and gRPC, Snowflake, S3 and Kafka as extras. Six or more years of professional web development is the reported requirement. The guide covers each reported round, the reported questions with worked approaches for the behavioral ones, and a seven-day plan. Reported questions vary by team, so treat them as patterns rather than a fixed list.
Candidates report four rounds over roughly three to five weeks: Initial Screening, Coding Interview, System Design Interview and Behavioral Interview. The questions vary by team, so use them as patterns.
Focus areas
- GraphQL
- TypeScript
- Node.js
Overview
The role is full stack with a clear centre of gravity. You build the user interface, you build the GraphQL API behind it, and you keep the integrations with backend systems running. Preparation should follow that shape: schema and resolver design, how a React client with Apollo consumes the API, and the SQL underneath. The reported technical questions match this closely: REST versus GraphQL, SQL performance, the React component lifecycle, API security and TypeScript experience.
The reported question set is wide rather than deep. It includes two basic algorithm questions (reversing a linked list, searching a sorted array), three system design prompts (real-time processing of financial transactions, a microservices architecture for a financial application, a caching layer for an API), two case-study prompts (finding anomalies in a transaction dataset, prioritizing features for a new financial application) and a block of teamwork questions. Several are framed around financial transactions, but the techniques underneath are general: idempotent writes, ordering, cache invalidation, outlier detection and trade-off reasoning.
Because the reported requirement is six or more years of web development, prepare to talk about decisions you made and what they cost, not only definitions. For every topic, have one real project where you used it, one limitation you hit, and one alternative you rejected. Candidates also report ElasticSearch and Kafka as topics that may come up, and the nice-to-have list includes gRPC, Snowflake and S3, so know what each one is for and be honest about how deep your experience goes.
The plan at the end of this guide spends one day each on API design and security, the React and TypeScript layer, SQL, algorithms and system design, and a final day on behavioral stories and the product-prioritization question. Speak your answers aloud: an answer you have only read is much harder to deliver cleanly.
The Accern interview process
Candidates report these four stages in this order, over about three to five weeks in total. The descriptions below are what candidates share, not a published process.
Initial Screening
Candidates describe the Initial Screening as an assessment of your technical background and experience. Treat it as the first pass over your CV against the stack the role lists. Have a clear account of each project that involved TypeScript, Node, GraphQL, SQL or React: what you owned, what the data and traffic looked like, and what you would change. Short background questions such as REST versus GraphQL or what TypeScript gave your team are natural here, so keep those answers ready.
What to demonstrate
- Your technical background and the experience on your CV
- How your past work maps to the web, API and SQL work the role describes
How to prepare
- Write a short CV walkthrough that names, for each recent job, the stack, your part, and one measurable result you can defend.
- Prepare a two-sentence answer to why Accern's no-code AI platform for financial services interests you, based on what you actually read about it.
- Rehearse the REST versus GraphQL comparison and your TypeScript experience answer so both come out concrete rather than as feature lists.
Coding Interview
Candidates describe the Coding Interview as a chance to show coding skills and an understanding of algorithms. The reported coding questions are reversing a linked list and searching a sorted array, so the fundamentals matter more than exotic tricks. Write clean code in a language you know well (TypeScript is the natural choice given the stack), say your plan before typing, and test with edge cases before you declare it done.
What to demonstrate
- Coding skill shown through working code
- Understanding of algorithms and data structures, including their complexity
How to prepare
- Write iterative and recursive linked-list reversal in TypeScript and test the empty list, a single node and two nodes.
- Write binary search from scratch, then variants such as first or last occurrence of a duplicate, and practice explaining why the loop terminates.
System Design Interview
Candidates describe the System Design Interview as a test of your ability to design scalable and efficient systems. The reported prompts are real-time data processing for financial transactions, a microservices architecture for a financial application, and a caching layer for an API. Candidates also list Kafka and ElasticSearch among topics that can come up. Structure each answer the same way: requirements and scale, the data model and API, the main components, then failure handling and trade-offs.
What to demonstrate
- Ability to design scalable and efficient systems
- How you handle correctness and failure in a financial-transaction setting
- How you reason about trade-offs between alternatives
How to prepare
- Draw the transaction-processing design once end to end: ingestion, a partitioned log, idempotent consumers, a ledger store and an audit trail, and say what happens on duplicate or out-of-order events.
- For the caching layer, decide where the cache sits, the key design, TTL versus explicit invalidation, and how you prevent a stampede.
- Prepare a short explanation of when Kafka and ElasticSearch earn their place and when a database query would do.
Behavioral Interview
Candidates describe the Behavioral Interview as questions about interpersonal skills and leadership qualities. The reported prompts cover a hard technical challenge, conflict inside a team and communication in a remote environment. The role works with frontend and backend developers and product teams, so choose stories that show you aligning with people who hold different priorities. Prepare each story as situation, your decision, the result, and what you would change.
What to demonstrate
- Interpersonal skills and how you work inside a team
- Leadership qualities, including how you influence others without formal authority
- Communication, including in a remote setting
How to prepare
- Write four stories: a technical challenge, a team conflict, a remote-communication example, and a time you explained a technical concept to a non-technical person.
- Attach one real number or observable result to each story, and write down what you would do differently.
- Practise telling each story out loud so the decision you personally made comes early, not last.
Where candidates lose points
Answering REST versus GraphQL as a feature list
Compare on concrete axes: over- and under-fetching, endpoint versioning versus schema evolution, HTTP caching versus a normalized client cache or persisted queries, the N+1 resolver problem and batching with a DataLoader pattern, errors returned alongside data, and query depth or cost limits. Finish with a case where REST is the better choice.
Reciting class-component lifecycle method names for the React question
Explain mount, update and unmount in terms of function components: render, effects with useEffect, cleanup functions, dependency arrays, and why development Strict Mode runs effects twice. Mention class methods only as a mapping.
Optimizing SQL by guesswork
Run EXPLAIN ANALYZE first and read it: sequential scan versus index scan, row estimates versus actuals, join order. Then fix the cause (missing composite index, a function wrapped around an indexed column, selecting unneeded columns, offset pagination) and re-measure.
Jumping to Kafka and microservices in the financial-transaction design before stating requirements
State the volume, latency target and correctness needs first. Then cover idempotency keys, ordering per account, at-least-once delivery with idempotent consumers, a ledger with an audit trail, and a plan for duplicate and failed events. Justify each component by a requirement.
Telling behavioral stories in the first person plural with no personal decision or result
For each story write down the decision you made, the alternative you rejected, the measurable result, and what you would change. Practise it aloud until the decision comes within the first few sentences.
Questions & practice
Write a function to reverse a linked list.
Medium · Coding / Algorithms
Approach
- Use the iterative three-pointer method. Start with prev = null and curr = head. In each step, save next = curr.next, set curr.next = prev, then move prev = curr and curr = next. When curr is null, return prev as the new head. This is O(n) time and O(1) extra space.
- Know the recursive version. Reverse the rest of the list, then set head.next.next = head and head.next = null. It is also O(n) time but uses O(n) call-stack space, so a very long list can overflow the stack.
- Cover the edge cases: an empty list (return null), a single node and two nodes. Check that the old head's next ends up null, or the result contains a cycle.
- Type it cleanly in TypeScript, for example class ListNode { val: number; next: ListNode | null }. Test by walking the returned list and comparing its values with the reversed input array.
- Note the doubly linked variant. There you swap prev and next on every node and return the last node visited.
Follow-up
- Reverse only the nodes between positions m and n in a single pass.
- Reverse the list in groups of k nodes, leaving a short final group as it is.
- Check whether a linked list is a palindrome using O(1) extra space.
How would you implement a search algorithm to find a specific item in a sorted array?
Medium · Coding / Algorithms
Approach
- Use binary search, which needs sorted data with random access. Keep lo and hi, compute mid = lo + floor((hi - lo) / 2) (written this way to avoid integer overflow in fixed-width languages), compare and discard half each step. This is O(log n) time and O(1) space, compared with O(n) for a linear scan.
- State the loop invariant. With a closed interval, use while (lo <= hi), hi = mid - 1 and lo = mid + 1. With a half-open interval [lo, hi), use while (lo < hi) to find the lower bound, the first index whose value is >= target. The lower bound also gives the insertion point when the target is absent.
- Cover the edge cases: an empty array, a target below the first or above the last element, a single element, and duplicates (return the first or last occurrence by searching for a bound instead of stopping at any match). Watch for infinite loops when lo = mid is combined with a mid that rounds down.
- Know the library behaviour. Python's bisect_left and bisect_right return insertion points. Java's Arrays.binarySearch returns -(insertion point) - 1 when the key is absent, and makes no guarantee about which duplicate it finds. JavaScript has no built-in binary search.
- Mention the variants. Interpolation search averages O(log log n) on uniformly distributed keys but degrades to O(n). Exponential search finds a range in O(log i) when the size is unknown. For very small arrays, a linear scan can be faster in practice.
Follow-up
- Find a target in a sorted array that has been rotated at an unknown pivot.
- Return the first and last index of a target that appears many times.
- Use binary search on the answer, for example to find the minimum ship capacity that delivers all packages within D days.
Collapse a redelivered event batch into per-aggregate high-water marks
Easy · hashing · at-least-once · aggregation
You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.
Approach
- One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
- Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
- Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
- If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.
Follow-up
- The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
- How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?
How do you optimize SQL queries for performance?
Medium · Technical / Domain Questions
Approach
- Measure before changing anything. In Postgres, run EXPLAIN (ANALYZE, BUFFERS) on the slow query and look for sequential scans on large tables, row estimates far from actual counts, and nested loops with a large outer side.
- Index for the access pattern. Put B-tree indexes on filter and join columns. In a composite index, list equality columns before range columns, because only the leftmost prefix is usable. Add INCLUDE columns to get an index-only scan.
- Keep predicates sargable. WHERE lower(email) = ... cannot use a plain index on email (it needs an expression index), a leading-wildcard LIKE '%x' cannot use a B-tree, and an implicit type cast on the column can disable the index.
- Reduce the work. Select only the columns you need. Filter before you join or aggregate. Replace deep OFFSET pagination with keyset pagination (WHERE id > last_id ORDER BY id LIMIT n). Remove N+1 query patterns in application code.
- State the costs and the remaining levers. Every index slows writes and uses storage. Stale statistics mislead the planner, so run ANALYZE. Very large time-series tables can be partitioned, and heavy repeated aggregates can move to a materialized view.
Follow-up
- An index exists but the planner still chooses a sequential scan. What are the likely reasons?
- How do you paginate efficiently to page 10,000 of a result set?
- How would you decide whether an additional index is worth its write cost?
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 the difference between REST and GraphQL.
Medium · Technical / Domain Questions
Approach
- Contrast the models first. REST exposes one URL per resource and uses HTTP verbs and status codes. GraphQL usually serves a single endpoint backed by a typed schema, and the client selects exactly the fields it needs through queries, mutations and subscriptions.
- Name the fetching trade-off. REST endpoints tend to over-fetch, or under-fetch and force extra round trips. GraphQL fixes that for the client but moves the cost to the server: each field has a resolver, so a list of 50 items can trigger 50 child lookups (N+1) unless you batch them per request with DataLoader.
- Cover caching. A REST GET can be cached by URL in browsers and CDNs. A GraphQL POST body is not HTTP-cacheable by default, so you rely on a normalized client cache (Apollo InMemoryCache keys objects by __typename plus id) or on persisted queries sent over GET.
- Cover errors and evolution. GraphQL commonly returns HTTP 200 with an errors array next to partial data, while REST branches on status codes. REST versions with /v2 paths; GraphQL evolves one schema, adds fields and marks old ones with @deprecated.
- Close with when you would pick each. GraphQL suits UI-driven aggregation across backends. REST suits simple public APIs, webhooks, file downloads and edge caching. Note the extra GraphQL hardening it needs: depth and cost limits on queries.
Follow-up
- How would you stop N+1 queries in a GraphQL resolver that loads each item's owner?
- How would you cache GraphQL responses at a CDN?
- When would you keep a REST endpoint next to a GraphQL API?
Can you describe the lifecycle of a React component?
Medium · Technical / Domain Questions
Approach
- Give the class-component phases. Mounting runs constructor, getDerivedStateFromProps, render and componentDidMount. Updating runs getDerivedStateFromProps, shouldComponentUpdate, render, getSnapshotBeforeUpdate and componentDidUpdate. Unmounting runs componentWillUnmount. Error boundaries use getDerivedStateFromError and componentDidCatch.
- Map the lifecycle to hooks. Render must stay pure, and React then commits DOM changes. useEffect runs after the browser paints, and its cleanup runs before the next run of the effect and on unmount. useLayoutEffect runs synchronously after DOM mutations and before paint. The dependency array decides when an effect runs again.
- Say what triggers a re-render: a state update, a parent re-render or a change to a consumed context. React.memo, useMemo and useCallback can skip work. A key gives a component its identity, so changing the key unmounts and remounts it.
- Mention StrictMode. In development, React 18 double-invokes render and runs mount, unmount and mount again for effects. That exposes effects with missing cleanup; it does not happen in production builds.
- Name the common bugs. Stale closures capture old state in effects. Out-of-order async fetches can overwrite newer data; fix that with an AbortController or an ignore flag in the cleanup. Apollo's useQuery hook manages that fetch lifecycle for you.
Follow-up
- Why does my effect run twice in development but once in production?
- When would you use useLayoutEffect instead of useEffect?
- How do you prevent a slow earlier request from overwriting newer data in an effect?
What are some security best practices when developing APIs?
Medium · Technical / Domain Questions
Approach
- Authentication: use OAuth 2.0 or OIDC with short-lived access tokens. Verify the JWT signature, exp, iss and aud, and pin the accepted algorithms rather than trusting the token header. Rotate refresh tokens, and store API keys as hashes.
- Authorization on every object. Broken object level authorization is first in the OWASP API Security Top 10 (2023), so check ownership in the service or resolver layer for each record, not only at the route. In GraphQL, enforce access on fields and nested resolvers as well.
- Input and output. Validate request schemas and payload size. Use bind parameters, never string-built SQL. Return explicit response shapes so internal fields are not exposed, and reject unknown fields on writes to prevent mass assignment.
- Transport and browser: TLS everywhere with HSTS, a CORS allowlist instead of * on credentialed endpoints, and secrets kept in a secrets manager rather than in code or logs.
- Abuse controls and audit. Rate-limit by key, user and IP. Cap page sizes, and for GraphQL cap query depth and cost. Use idempotency keys on money-moving writes. Keep audit logs that leave out tokens and personal data, and scan dependencies.
Follow-up
- How do you revoke a JWT before it expires?
- How would you enforce field-level authorization in a GraphQL schema?
- What would you rate-limit on, and what does the client see when it hits the limit?
Design a system that handles real-time data processing for financial transactions.
Medium · System Design / Architecture
Approach
- Pin the requirements first: events per second, end-to-end latency, ordering needs (usually per account), the duplicate tolerance (none for balances) and audit retention. Then split the design into an ingest path, a processing path and a query path.
- Ingest through a gateway that validates each request and requires an idempotency key, then appends the event to a durable log such as Kafka. Partition by account id so each account's events stay in order. Store processed keys so a retried request is not applied twice.
- Process with stream consumers (Kafka Streams or Flink) that enrich, validate, score for fraud and maintain per-account aggregates in a state store. Window by event time and use watermarks so late events land in the correct window.
- Be precise about delivery. Consumers see at-least-once delivery by default. Kafka transactions give exactly-once only inside Kafka. For an external sink, make writes idempotent (upsert keyed on transaction id) or use a transactional outbox, and keep an append-only double-entry ledger as the source of truth.
- Plan for failure and scale. Send poison messages to a dead-letter topic. Alert on consumer lag. Replay from stored offsets after a logic fix. Handle a hot partition from one very large account by sub-keying it. Feed analytics stores (for example S3 or Snowflake) and a search index from the same log.
Follow-up
- A consumer writes to the database and crashes before committing its offset. What happens, and how do you make that safe?
- How would you reprocess a week of transactions after fixing a scoring bug?
- One account produces 100 times the normal volume. What changes in your partitioning?
How would you implement a microservices architecture for a financial application?
Medium · System Design / Architecture
Approach
- Split by bounded context (for example accounts, payments, ledger, notifications and reporting). Each service owns its data store, and no service reads another's tables, because a shared database brings back the coupling you split to remove.
- Choose communication by need. Use synchronous REST or gRPC where the caller needs an answer now. Use asynchronous events on a log such as Kafka to propagate state changes. Put a gateway, or a GraphQL layer that composes services, in front of the frontend.
- Handle cross-service writes without two-phase commit. Use a saga (orchestrated or choreographed) with compensating actions for each step. Use the transactional outbox pattern so the database write and the event publish cannot diverge, and make every consumer idempotent.
- Build in resilience: timeouts on every call, retries with exponential backoff and jitter only for idempotent operations, circuit breakers, and mTLS between services. Add distributed tracing (OpenTelemetry) with correlation ids, centralized logs and an audit trail for money movements.
- State the cost. Microservices add deployment, observability and data-consistency overhead. For a small team or a new product, a modular monolith with clean module boundaries can be split later along the same lines.
Follow-up
- A payment succeeds but the notification service is down for an hour. What does the user experience, and what recovers it?
- How would you migrate an existing monolith to this architecture without a big-bang cutover?
- How do you change an event's schema when three services consume it?
Describe how you would approach designing a caching layer for an API.
Medium · System Design / Architecture
Approach
- Decide what is cacheable. Look for read-heavy data that tolerates some staleness and is expensive to compute. Build the cache key from every input that changes the response (tenant, user or permission scope, query parameters), or one user's data can be served to another.
- Pick the layers. HTTP caching uses Cache-Control and ETag with 304 responses, a CDN can serve public GETs, Redis can be the shared application cache and an in-process LRU can hold hot keys. For GraphQL, add the Apollo normalized client cache, per-request DataLoader memoization and persisted queries over GET for edge caching.
- Choose a write strategy. Cache-aside reads the cache, loads from the database on a miss and sets the value with a TTL. Write-through updates the cache on every write. On updates, delete the key after the database commit and keep the TTL as a backstop for missed invalidations.
- Protect against stampedes and outages. Collapse concurrent misses for one key into a single load, add jitter to TTLs so keys do not expire together, serve stale data while revalidating, and cache negative results briefly. If Redis is down, fall back to the database behind a rate limit.
- Operate it with metrics: hit ratio, p50 and p99 latency with and without the cache, memory use and eviction policy (for example allkeys-lru in Redis). Skip the cache for strongly consistent data such as account balances.
Follow-up
- A read fills the cache with an old value just after a write invalidates it. How do you prevent that race?
- How do you invalidate a cached list when one item in it changes?
- What would you refuse to cache in a financial API, and why?
Given a dataset of financial transactions, how would you identify anomalies?
Medium · Problem-Solving / Case Studies
Approach
- Clarify the setup. Are fraud labels available? Is detection real-time or batch? What counts as anomalous (amount, frequency, location, new counterparty)? What does a false positive cost compared with a missed case? That last answer sets the alert threshold.
- Start with per-account baselines. Compare each amount to that account's history. Amounts are heavy-tailed, so log-transform them or use median and MAD instead of mean and standard deviation. Add velocity features (transactions in the last hour), time of day and new device or merchant flags.
- Show the SQL. Use window functions partitioned by account and ordered by time, with a frame that ends one row before the current row (ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING) so a transaction does not score against itself. Flag rows that exceed a robust threshold.
- Scale up with models. Without labels, use unsupervised detectors such as Isolation Forest, local outlier factor or autoencoder reconstruction error. With labels, train a supervised model such as gradient boosting. Classes are very imbalanced, so evaluate with precision-recall or PR-AUC rather than accuracy.
- Handle the edges. Score new accounts with little history against a peer-group or population baseline. Retrain or re-baseline as spending patterns drift. Cap alerts at what reviewers can handle, and feed their decisions back as labels.
Follow-up
- How would you score an account that has only two transactions so far?
- How would you check the detector works when you have no labels?
- What changes if the check must run before each transaction is approved?
How would you prioritize features in a product roadmap for a new financial application?
Medium · Problem-Solving / Case Studies
Approach
- Clarify the target user, the business goal and the success metric before ranking anything. Separate the baseline items a financial product cannot launch without (authentication, security controls, audit logging, regulatory requirements) from features that compete on value.
- Score the remaining features with a consistent framework. RICE is Reach x Impact x Confidence / Effort. MoSCoW sorts features into must, should, could and won't. Say how you estimate each input and that confidence reduces the score of speculative ideas.
- Order by dependencies. Shared foundations such as the data pipeline, the API layer and permissions come before the features built on them. Choose the smallest release that tests the riskiest assumption with real users.
- Bring the engineering view: effort ranges rather than single numbers, technical risk, and the maintenance cost a feature adds. State plainly what you are cutting and why.
- Plan to revisit the order. Set up usage metrics and user feedback for each release, and re-rank when evidence changes the impact or confidence scores.
Follow-up
- A senior stakeholder insists on a feature that scores low. How do you handle it?
- A new compliance requirement arrives mid-quarter. What happens to the roadmap?
- How do you estimate effort for a feature your team has never built?
Edge instances grow 400 MB per hour until the nightly restart
Hard · memory leak · heap analysis · metric cardinality
Edge API instances start at 700 MB resident and grow about 400 MB/hour; a nightly rolling restart has hidden it for weeks. Growth continues unchanged when request rate halves overnight, p99 degrades in the last hours before an instance is recycled, and heap used immediately after a forced full GC rises monotonically. The service holds no product state. Name the discriminating measurement that separates the plausible causes, give the most likely cause, and give the fix and how you would verify it.
Approach
- Separate resident memory from live heap first, because they fail differently. Resident size can grow from fragmentation, native buffers or thread stacks while the heap is flat; heap used after a full GC rising monotonically is the measurement that says objects are reachable and not being released. You already have it, so this is retention, not fragmentation, and that closes off half the candidate list.
- Use the rate's independence from traffic as the discriminator. Growth that continues at half the request rate rules out per-request objects that are merely slow to collect and points at a structure that grows with distinct values observed rather than with call volume. Write the candidates that have that property: a metrics registry keyed on a high-cardinality label, an unevicted cache, an interner, a per-key lock map.
- Take two heap snapshots an hour apart and diff by retained size, reading the dominator tree, not by allocation count or instance count. Expect one root holding a map with millions of entries, then follow the reference chain to the code that inserts and never removes. Allocation profilers point at churn, which is the wrong signal here.
- The candidate that fits this service is an observability label carrying an identifier, such as a request path recorded before templating so that /v1/resources/48213 becomes its own metric series. That grows with distinct ids seen, is independent of rate, and explains the late p99 degradation, since GC cost rises with the size of the live set.
Follow-up
- Post-GC heap is now flat but resident size still creeps. What are you looking at, and does it matter?
- How would you have detected this before an OOM, given the nightly restart masked the trend?
Suggested practice checklist
The plan follows the four reported rounds and the reported question types: one day each for API design and security, the React and TypeScript layer, SQL, algorithms and system design, then a final day for behavioral stories and the case-study questions. Every day ends with something written or spoken that you can review.
Day 1 — Map the loop and the stack
- Write the four reported rounds in order and one sentence on what each covers.
- List the stack the role names (TypeScript, Node, GraphQL, SQL, React, Apollo GraphQL) and the extras (ElasticSearch, Kafka, gRPC, Snowflake, S3), and rate your depth in each honestly.
- Write a short CV walkthrough that names a project and a result for each of the main technologies.
Deliverable: A one-page round map, a rated stack inventory with the three weakest items marked, and a written CV walkthrough.
Day 2 — GraphQL, REST and API security
- Write a comparison of REST and GraphQL on at least six axes (fetching, versioning, caching, errors, tooling, performance risks) and finish with when REST wins.
- Build a small TypeScript and Node GraphQL schema with a nested resolver, demonstrate the N+1 problem and fix it with batching.
- Write an API security checklist covering authentication, authorization per field, input validation, rate limiting, query depth and cost limits, and secrets handling.
Deliverable: A comparison table, a working schema with the batched resolver, and a security checklist you can speak from.
Day 3 — React, Apollo and TypeScript
- Write out the React component lifecycle for function components with useEffect and cleanup, and a note on how state is managed as an app grows.
- Build a small component that loads data with an Apollo query, updates the cache after a mutation, and handles loading and error states.
- Prepare your TypeScript answer around a real project: gains, costs, and one runtime-validation example.
Deliverable: A lifecycle cheat sheet, a working Apollo component, and a written TypeScript answer built on your own project.
Day 4 — SQL performance and anomalies
- Take a slow query on a table of at least a few hundred thousand rows, read EXPLAIN ANALYZE, add the right index and record the before and after plans.
- Write a SQL query that flags anomalous transactions per account using a percentile or standard-deviation threshold, and list its limits.
Deliverable: Before and after query plans, an anomaly query with its caveats, and a solved window-function practice question.
Day 5 — Algorithms in TypeScript
- Write iterative and recursive linked-list reversal, with tests for empty, single and two-node lists, and state time and space for each.
- Write binary search and the first- and last-occurrence variants; explain the invariant and how you avoid off-by-one errors and integer overflow in the midpoint.
Deliverable: Tested reversal and binary search functions, plus a spoken walkthrough of the practice problem.
Day 6 — System design for money-moving systems
- Design real-time processing of financial transactions end to end: ingestion, partitioning key, idempotent consumers, ledger storage, audit trail and replay.
- Sketch a microservices architecture for a financial application: service boundaries, synchronous versus event-driven calls, and how a multi-service operation stays consistent.
- Design an API caching layer: cache placement, key design, invalidation and stampede protection, and write a short note on where Kafka or ElasticSearch would and would not help.
Deliverable: Three diagrams with a written list of trade-offs for each, and a short note on the Kafka and ElasticSearch fit.
Day 7 — Behavioral stories, prioritization and debugging
- Write and speak four stories: a hard technical challenge, a team conflict, a remote-communication example and one on explaining a technical idea to a non-technical person.
- Prepare a prioritization answer for a new financial application's roadmap using reach, impact, confidence and effort, plus a dependency check.
Deliverable: Four spoken stories, a one-page prioritization framework with an example ranking, and a written debugging sequence.
Stories for the Accern behavioral round
Candidates report a Behavioral Interview aimed at interpersonal skills and leadership, with prompts on technical challenges, team conflict and remote communication. The role works with frontend and backend developers, product teams and other engineers, so pick stories that show you working across those lines. The TypeScript experience prompt is filed with the behavioral questions, so answer it with a real project, not a feature list.
- Describe a time when you had to explain a technical concept to a non-technical audience.
- How do you ensure all team members are aligned on project goals?
Discuss your experience with Typescript and its advantages over JavaScript.
Medium · Technical / Domain Questions
Approach
- Open with one concrete project: whether you adopted TypeScript, migrated a JavaScript codebase, or worked in a typed codebase daily, and which decisions were yours (compiler flags, shared types, how API responses were typed).
- Give advantages tied to what you saw: the compiler catches wrong property names and unhandled null or undefined (strictNullChecks), renames and refactors are safe across files, signatures and props document themselves, and types generated from a GraphQL schema keep client and server in agreement. Name one real bug class it caught.
- State the costs honestly: a build step, types are erased at runtime so API responses and JSON still need validation, any and type assertions silently switch checking off, and heavy generics can hurt readability.
- If you migrated, describe the incremental path: allowJs, converting files gradually, switching on strict options per directory, and only claim a measured result (fewer production type errors) if you really measured one.
- Close with a position: plain JavaScript can be fine for a tiny script, while TypeScript pays off in a long-lived codebase with several developers. A claim that TypeScript prevents all bugs sinks the answer.
Follow-up
- What are the downsides, and when did TypeScript get in your way?
- Types are erased at runtime, so how do you validate data coming from an API or a form?
- What is the difference between unknown and any, and when would you use each?
Describe a time you faced a significant technical challenge. How did you resolve it?
Medium · Behavioral / Leadership
Approach
- Pick a challenge where the difficulty was truly technical and the decision was yours: a production bug with no obvious cause, a performance cliff, a risky migration or a tricky integration. State the situation and the stakes in two sentences.
- Show your sequence rather than the outcome: how you reproduced it, which logs, metrics or traces you added, the hypotheses you listed, how you bisected, and what you ruled out and why.
- Name the decision point: the options you weighed (patch versus redesign, rollback versus fix forward), the one you chose, and the trade-off you accepted knowingly.
- Quantify the result with figures you actually measured, such as latency, error rate or hours saved, then say what you added so it would not recur: a test, an alert or a runbook.
- Use I for your own actions and credit teammates by role for theirs. The usual mistake is a story that stays at the symptom level and never reveals your reasoning.
Follow-up
- What would you do differently if you faced it again?
- How did you know the fix addressed the root cause and not a symptom?
- What did you do when your first hypothesis turned out to be wrong?
How do you handle conflicts within a team?
Medium · Behavioral / Leadership
Approach
- Choose a disagreement about the work, not a personality clash: for example the shape of a GraphQL schema between frontend and backend developers, build versus buy, or scope against a deadline.
- State the other person's position fairly in one sentence, including the constraint behind it. This shows you understood them before you acted.
- Describe the steps: a one-to-one conversation first, agreeing on the shared goal, then turning opinions into evidence with a small prototype, a benchmark or a short written comparison, and involving a third person only if you were still stuck.
- Explain how the decision was made and that you committed to it even when it was not your preferred option, then give the result for the project and for the working relationship afterwards.
- Avoid three traps: a villain story, claiming you have never had a conflict, and an ending where you simply won.
Follow-up
- What if the other person still disagreed after you showed the data?
- When do you escalate a disagreement, and when do you let it go?
- Tell me about a time you were the one who turned out to be wrong.
What do you do to ensure effective communication in a remote work environment?
Medium · Behavioral / Leadership
Approach
- Answer with practices plus one example. Start with your working agreements: what goes in writing (design notes, decisions, pull request descriptions with context and test plan, updates on Jira tickets or Confluence pages) and what goes on a call (ambiguity, disagreement, sensitive feedback).
- Describe your asynchronous habits: status updates that state blockers and what you need from whom, decisions logged where others can find them, questions that include what you already tried, and documents with named owners.
- Cover time zones and availability: overlap hours, handoff notes at the end of a day, and making a reversible default decision and flagging it so work is not blocked waiting for a reply.
- Give one concrete story where missing context or a misunderstanding would have cost something, and the specific habit you changed afterwards.
- Show that you adapt to the audience: lead with the summary for non-technical stakeholders, give detail for engineers, and confirm understanding by asking people to restate the next steps.
Follow-up
- How do you reach alignment when teammates are in different time zones?
- What do you do when a chat thread keeps growing without a decision?
- How do you explain a technical trade-off to a non-technical stakeholder?