cswork / libraryOpen practice workspace

Interview guides · Ankix

Ankix Software Engineer Interview Guide

Ankix Software Engineer interview guide: HR screening, profile matching and technical rounds, with stack-specific questions and a 7-day prep plan.

The 60-second brief

Candidates describe Ankix as a technology consulting and IT outsourcing company. Engineers are placed on projects for external clients, so the stack and the industry depend on the project you are matched with. The stacks that appear in reported roles include enterprise Java, .NET with React, Python, GCP cloud architecture, Appian and UiPath automation, and job titles range from Python Developer to Staff Java Backend Developer and Cloud Architect. Candidates also report that many positions are listed as home office within Portugal, with some tied to Lisbon.

This guide is for candidates interviewing for a Software Engineer role at Ankix, from junior to senior. It covers the three reported rounds (HR Screening, Profile Matching, Technical Assessment), the fifteen questions candidates report across HR, stack-specific and behavioral topics, and a seven-day plan. Because the technical stage depends on the client project, the guide helps you prepare one primary stack in depth and the shared fundamentals every stack reports: error handling, databases, REST APIs, React state and cloud availability.

Candidates report three rounds over roughly 3-5 weeks: HR Screening, Profile Matching and a Technical Assessment. The first two are conversational and about fit with open projects; the technical stage varies with the client and the seniority of the role.

Focus areas

  • Cloud Resiliency
  • .NET
  • Cloud Architecture

Overview

The loop is shaped by the way Ankix works. Candidates report that the first conversation is with a recruiter or HR representative, that it is low-pressure, and that it is about your background, your preferred technologies, your salary expectations and whether you want fully remote or hybrid work in Lisbon. The recruiter also describes open client projects, so the screen works in both directions. Your preparation for these rounds is mostly rehearsal: a clear career story, a stack you can name with evidence, a salary figure you have researched, and a straight answer on location.

The technical stage is where candidates report the most variation. Depending on the project, it may be an assessment or a conversation with the client's engineering team, and the rigor differs between a junior Python role and a senior GCP architect role. The reported technical questions are fundamentals that you can answer from your own experience: exception handling and debugging in Java, Python or .NET, relational versus non-relational databases, building a RESTful API from scratch, state and lifecycles in React, and a secure, highly available design on GCP. Choose the stack you would be matched on and prepare it to the level of real examples, then keep the other questions at the level of sound principles.

The behavioral questions candidates report have a consulting flavor. They ask about disagreeing with a senior colleague or client, delivering under tight deadlines, staying visible and aligned while fully remote, explaining a technical problem to a non-technical stakeholder, and prioritizing several urgent requests. Prepare four or five real stories and map each to more than one of these prompts, so you are adapting a story rather than inventing one under pressure.

Finally, treat logistics as part of the preparation. Candidates report that background verification can be strict, that Portuguese and/or English communication is required, and that feedback can be slow or missing when no project match is found. Collect certificates, diplomas and references before you start, and plan to follow up with the recruiter yourself.

The Ankix interview process

Candidates report three stages over roughly 3-5 weeks. The exact number of technical conversations changes with the client project, so treat the order below as the typical path rather than a fixed process.

HR Screening

Candidates describe the HR Screening as a call with a recruiter or HR representative that is conversational rather than technical. You introduce yourself, go through your academic and professional background, name your technical competencies and say what salary and working model you want. Candidates report that salary expectations come up in this first conversation. Approach it as a structured pitch: a short chronological story, a primary stack backed by one concrete project, a researched salary figure and a clear position on remote versus hybrid.

What to demonstrate

  • Whether your academic and professional background is clear and consistent with the projects open
  • Whether you can name your core competencies and preferred technologies concisely
  • Whether your salary expectations and working-model preferences are workable
  • Communication and professionalism in a client-facing consultancy setting

How to prepare

  • Write and rehearse your answer to the introduction and academic trajectory question as a chronological story that ends on the stack you want to work in.
  • Prepare a competencies answer with one primary stack, one or two secondary ones, and a project that proves each.
  • Research a salary range for your stack and seniority in Portugal (or your region) and decide a target figure and a floor before the call.
  • Prepare a one-sentence answer on fully remote versus hybrid in Lisbon, and a question about the end-client.

Profile Matching

In Profile Matching, candidates report a discussion of the project opportunities that fit your profile, together with some assessment of your qualifications. The recruiter pitches projects and you react to them. Candidates also warn that a pitched project can differ from the posting you applied to, because postings at consulting firms are broad. Approach it as a two-way conversation: show flexibility, but ask which client, industry, team and stack the project involves so you can aim your technical preparation.

What to demonstrate

  • How well your skills and motivations match an active client project
  • Whether your preferred industries and project types line up with what is available
  • Your flexibility when a project differs from the original posting
  • How clearly you articulate your goals and availability

How to prepare

  • Write down two or three industries or project types you want and the reason for each, so you can answer the question about what motivates you.
  • List the questions you want answered about the end-client: industry, team structure, stack, seniority expected and whether work is remote or on site.
  • Prepare a sentence that links your strongest project to a different stack, for example a Java service experience pitched for a GCP-based project.
  • Keep your certificates and a list of references at hand, since candidates report strict credential checks.

Technical Assessment

The Technical Assessment is described as a stage of technical assessments or interviews with the client's engineering team, and candidates say the rigor depends on the project. A junior Python role and a senior GCP architect role are reported to differ a lot. Reported questions here are stack fundamentals: exception management and debugging, relational versus non-relational databases, building a REST API, React state and lifecycles, and secure highly available design on GCP. Approach it by anchoring each answer in a project you have worked on.

What to demonstrate

  • Depth in your primary language and framework, whether Java, Python, C# or .NET
  • Fundamentals that cross stacks: error handling, data storage choices and API design
  • For senior or architect roles, cloud design including availability and security
  • Willingness to adapt to the client's tools and codebase

How to prepare

  • Write a compact answer for exception handling and debugging in your main language, with the concrete constructs and a real debugging story.
  • Prepare a decision rule for relational versus non-relational storage and a worked example of each.
  • Practise walking through a REST API build in order: resources, verbs, validation, status codes, persistence, authentication, tests, documentation.
  • If your track includes React or GCP, prepare state management with hooks and a GCP design covering regions, load balancing, IAM and backups.

Where candidates lose points

Reading your CV line by line in the HR Screening, with no stack and no destination

Build the introduction as a chronological story that ends on the stack and project type you want. Give each role one verifiable result, because the recruiter is matching you to client work.

Giving a vague or unresearched answer to the salary question

Candidates report that salary expectations come up in the first interview. Check market ranges for your stack and seniority in Portugal or your region, then decide a target and a floor and say the target plainly.

Claiming every stack on the list (Java, .NET, Python, GCP, Appian, UiPath) and having depth in none

Name one primary stack with a real project, one or two secondary ones, and say you adapt quickly. Prepare the shared fundamentals so you can answer exception handling, databases and REST API design in any stack.

Treating the remote versus Lisbon hybrid question or the project pitch as a formality

Give a definite answer on remote or hybrid, ask about the end-client, industry and team, and stay open when the pitched project differs from the posting you applied to.

Behavioral stories with no client angle: a disagreement you won, or a deadline you met only by working late

Frame each story around evidence, scope trade-offs and communication with a client or senior stakeholder, and say what you would do differently.

Questions & practice

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

Medium · top-k · heavy hitters · streaming

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

Approach

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

Follow-up

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

Merge partitioned event streams into one ordered feed with bounded lateness

Hard · k-way merge · watermarks · out-of-order streams

The read-model service consumes 64 log partitions carrying about 4,000 events per second in total. Each partition is ordered within itself, but partitions drift by up to 30 seconds, and the activity feed must present a tenant's events in occurred_at order. Produce the merge. State its complexity, the buffer it requires in events and in bytes, what happens when one partition is idle, and what you do with an event that arrives after you have already emitted its position. Payloads average 1 KB.

Approach

  1. Merge with a min-heap over the 64 partition heads keyed on (occurred_at, event_id): O(log P) per event and O(n log P) overall. The tie-break on event_id is what makes the output deterministic when two partitions carry the same millisecond, which matters because the feed is paginated and a non-deterministic order reorders pages under the reader.
  2. Emitting the heap head is only correct once every partition has produced everything up to that timestamp, so the emit condition is a watermark: the minimum across partitions of the highest occurred_at seen, less the allowed lateness. Events are held until the watermark passes them, which is what turns individually ordered streams into a jointly ordered one.
  3. Size the buffer from the lateness rather than guessing: 4,000 events per second times 30 seconds is 120,000 buffered events, and at 1 KB each about 120 MB of heap. That number is the real price of the ordering guarantee and belongs in front of whoever asked for it.
  4. Handle the idle partition explicitly, because it fails the feed rather than corrupting it: a partition with no traffic never advances its own maximum, so the watermark freezes and output stops entirely. Either every partition emits a periodic idle marker carrying the broker's current time, or the watermark falls back to wall clock for a partition silent beyond a threshold.

Follow-up

  • The lateness budget is raised to five minutes. What is the new buffer, and what besides memory changes?
  • The consumer restarts. Where does it resume from, and what does the feed look like for the first 30 seconds?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Denormalise tenant onto revisions and backfill it live

Hard · denormalisation · online migration · backfill

resource_revision (revision_id, resource_id, version, actor_user_id, change_kind, patch, request_id, created_at) has 400M rows and no tenant column; tenant_id lives only on resource. Two reads need it: a tenant-scoped audit feed ordered by created_at DESC, and an offboarding purge. Both join back to resource today. Justify adding tenant_id to resource_revision against those two reads, name the anomaly the copy introduces and the constraint that prevents it, then give the ordered migration for a live table taking 1.2k writes/second — the lock each step takes, how the backfill is batched, and where each step stops being reversible. PostgreSQL 16.

Approach

  1. Justify from the access path rather than from taste. Without the column, the audit feed either scans resource_revision by created_at and discards other tenants' rows, or resolves the tenant's resource_ids first and probes with them — both proportional to the tenant's whole history rather than to one page. With (tenant_id, created_at DESC, revision_id DESC) it is a seek that stops at 50 rows, and the purge becomes a ranged delete instead of a join.
  2. Name the cost exactly: a second copy of a fact can disagree with the first. Make the disagreement unwritable rather than documented — add UNIQUE (resource_id, tenant_id) on resource so it can serve as a foreign-key target, then FOREIGN KEY (resource_id, tenant_id) REFERENCES resource (resource_id, tenant_id) on the revision table. A revision can then only ever carry its parent's tenant.
  3. Step one, expand: ALTER TABLE resource_revision ADD COLUMN tenant_id BIGINT NULL, with no default, so it is a catalogue change and no rewrite. It still needs ACCESS EXCLUSIVE for an instant, and that instant queues behind the longest open transaction on the table while every later query queues behind it — set lock_timeout to 2s and retry rather than wait.
  4. Step two, dual-write: deploy the writer that populates tenant_id on every new revision while reads still use the join. Reversible by redeploying the previous build, because nothing reads the column yet.

Follow-up

  • The backfill is half finished and a rollback is required. What state is the table in, and what does the previous build do with a half-populated column?
  • How do you verify the backfill actually finished, given rows are still being inserted while it runs?

Hold a per-tenant active cap against concurrent creates

Hard · write skew · isolation levels · constraints

A tenant on the standard plan may hold at most 50 resources with status='active'. The create handler runs SELECT count(*) FROM resource WHERE tenant_id = $1 AND status = 'active', compares to 50, then inserts. Two creates arrive 3 ms apart on different instances and the tenant lands at 51. Name the anomaly, say whether PostgreSQL 16 READ COMMITTED or REPEATABLE READ prevents it and why, then give an implementation that holds the cap at READ COMMITTED with the exact statements. Finally, say what changes when the cap is 'at most one running export per tenant' on job_run.

Approach

  1. Name it: write skew. The two transactions read an overlapping set and write disjoint rows, so there is no row-level conflict for the engine to detect and each commit is individually legal.
  2. Rule out the levels precisely. READ COMMITTED takes a fresh snapshot per statement and takes no lock on the counted rows, so both see 49. PostgreSQL's REPEATABLE READ is snapshot isolation: it removes non-repeatable reads and phantoms within the snapshot but still admits write skew, because the anomaly is not a re-read of a changed row, it is a read of a set that a concurrent transaction invalidates. Only SERIALIZABLE closes it, by tracking the read dependency and aborting one transaction with SQLSTATE 40001 — a guarantee that exists only if the application re-runs the whole transaction from the read.
  3. Convert the set predicate into a single-row conflict: keep tenant.active_resource_count and run UPDATE tenant SET active_resource_count = active_resource_count + 1 WHERE tenant_id = $1 AND active_resource_count < 50 in the same transaction as the INSERT. Zero affected rows is the cap, returned as 409. The row lock serialises the decision at any isolation level, and contention is bounded to one tenant's row — which is also the fair-scheduling unit, unlike a global counter that would convoy every tenant behind one row.
  4. State the cost you just took on: a counter is a second source of truth that can drift, so every path that changes status must adjust it inside the same transaction, and a periodic reconciliation has to exist, with resource_revision as the authority for what the count should have been.

Follow-up

  • A resource moves from archived back to active. Which statements change, and what breaks if the counter update and the status change land in different transactions?
  • The cap becomes plan-dependent and a plan can change mid-month. Where does the number 50 live, and who reads it?

What are your key technical competencies and which technologies do you prefer working with?

Medium · HR, Background, and Motivation

Approach

  1. Lead with one primary stack you can defend in depth, for example: "My strongest stack is Java with Spring Boot; I have built and run REST services on it in production." Then name the specific pieces of it you know well: the framework, the build tool, the database and the test tooling.
  2. Separate the stack into three tiers: production depth, working knowledge and exposure. Saying "I have used React on two features but I am not a React specialist" is safer than listing every technology at the same level.
  3. Back each claim with one concrete artefact: a service you owned, a migration you ran, a pipeline you set up. A recruiter matching you to projects needs something they can pass on to a client team.
  4. Map your tiers onto the stacks candidates report for this role (Java, .NET with React, Python, GCP, UiPath, Appian). Say where you overlap, and which adjacent stack you could pick up quickly and why, for example C# from a Java background.
  5. State your preference and your flexibility together: "I prefer backend Java work, and I am open to a fullstack .NET/React project if the backend share is real." A preference with no flexibility, or flexibility with no preference, makes you hard to match.

Follow-up

  • Which of those technologies would you be comfortable being tested on live tomorrow?
  • What was the last technology you learned from scratch, and how long did it take before you shipped with it?
  • Would you take a project in a stack you have not used yet, such as UiPath or Appian?

What are your salary expectations for this role?

Medium · HR, Background, and Motivation

Approach

  1. Before the call, research the market range for your stack and seniority in your country (Portugal for most of the roles candidates describe) from salary surveys, job postings that publish ranges, and peers. Write down your floor, your target and the reasoning behind each.
  2. Give a range anchored on that research rather than one number, and set your target near the bottom of it: "Based on my experience with Java and cloud work, I am looking at X to Y gross per year." Candidates report this question comes up in the first interview, so have the answer ready then.
  3. Say exactly what the figure means: gross or net, annual or monthly, and how many monthly payments a year (Portuguese salaries are often quoted across 14 payments). Ambiguity here causes most of the later mismatches.
  4. Ask what goes with the base: meal allowance, remote-work allowance, travel to client sites, contract type, and whether pay changes with the client project you are placed on.
  5. Avoid naming a number below your floor to get matched faster. Lowering an expectation later is easy; raising one after it is on record is hard.

Follow-up

  • Is that range flexible if the project is fully remote?
  • What is your current package, and why are you looking to move?
  • Would you accept a lower base for a project in a domain you are more interested in?

Are you comfortable working fully remote, or do you prefer a hybrid setup in Lisbon?

Medium · HR, Background, and Motivation

Approach

  1. Give a clear preference first, then your real constraints: "I prefer fully remote. I can be in Lisbon for occasional planning sessions, but not every week." Candidates report that many roles are fully remote and some need a hybrid presence in Lisbon, depending on the end client.
  2. Show that remote work is something you already do well: your home setup and connectivity, overlap with the team's working hours, and how you make progress visible (written updates, short PRs, demos).
  3. If you are open to hybrid, give specifics: how many days, your commute, and from when. "Open to anything" gives the recruiter nothing to match on.
  4. Ask the questions that decide whether a hybrid offer works for you: which projects need on-site presence, whether that is set by the client, how travel to client sites is paid for, and whether the arrangement can change during the engagement.

Follow-up

  • If the best project match needed three days a week in Lisbon, would you take it?
  • How do you stay aligned with a team you have never met in person?
  • Which time zones can you overlap with?

What type of projects or industries are you most motivated to work in?

Medium · HR, Background, and Motivation

Approach

  1. Name two or three domains, each with a concrete reason taken from your history: "Financial services, because I built reconciliation jobs and I like the correctness constraints" is far stronger than "something with impact".
  2. Describe the kind of project as well as the industry: greenfield or legacy modernisation, integration-heavy work, cloud migration, automation. Many consulting projects are defined by the type of work more than by the sector.
  3. Say what you would rather not do, and why, without sounding rigid. This lets the recruiter filter projects for you before you spend time on interviews.
  4. Connect your motivation to growth: "I want a project where I own a service end to end on GCP" tells them what you are building toward and what to offer you.
  5. Ask which projects are open right now, and what industry, team size and stack each one has. Your answer can then refer to the projects that actually exist.

Follow-up

  • Why that industry over the others you have worked in?
  • What would make you want to leave a project early?
  • Would you take a project in an industry you have no experience in?

Can you explain the difference between relational and non-relational databases, and when you would use each?

Medium · Technical and Stack-Specific

Approach

  1. Relational databases (PostgreSQL, MySQL, SQL Server, Oracle) store normalised tables with a fixed schema, enforce constraints and foreign keys, support joins and ad-hoc SQL, and give multi-row ACID transactions. That fits data with many relationships and queries you cannot fully predict in advance.
  2. Name the non-relational families and give an example of each: key-value (Redis, DynamoDB), document (MongoDB, Firestore), wide-column (Cassandra, Bigtable) and graph (Neo4j). They are modelled around known access patterns, usually denormalised, and built to scale out horizontally by partition key.
  3. State the trade-off precisely: NoSQL stores avoid joins by duplicating data, so updating that data means writing it in several places. Many offer eventual or tunable consistency, and cross-partition queries are expensive or unsupported. Relational stores scale writes vertically or through sharding, which is operationally harder.
  4. Avoid the outdated binary: PostgreSQL has JSONB with GIN indexes for semi-structured fields, and MongoDB has supported multi-document transactions since 4.0. The choice comes from access patterns, consistency needs and scale, not from labels.
  5. Close with a concrete call: "For orders and payments I use PostgreSQL for transactional integrity. For a session store or a high-volume event feed read by key, I use Redis or a wide-column store. Polyglot persistence is fine if I can name who owns each copy of the data."

Follow-up

  • How would you model an order with line items in MongoDB, and what happens when a product name changes?
  • Your PostgreSQL primary is running out of capacity. What do you try before moving to NoSQL?
  • What does eventual consistency mean for a user who updates their profile and then reloads the page?

Walk me through how you would build a RESTful API from scratch.

Medium · Technical and Stack-Specific

Approach

  1. Start from the contract: identify the resources as plural nouns (/orders, /orders/{id}/items) and write the OpenAPI spec before the code, so clients and tests can work from it. Then pick the stack the project uses: Spring Boot, ASP.NET Core, or FastAPI/Flask.
  2. Use HTTP semantics correctly. GET is safe and idempotent, PUT and DELETE are idempotent, and POST is not. Return 201 with a Location header on create, 204 for an empty success, 400 or 422 for validation errors, 404, 409 for conflicts, and one consistent error body (RFC 9457 problem details).
  3. Layer the code as controller, service and repository. Validate input at the edge with DTOs (Bean Validation or data annotations, for example), keep business rules in the service layer, and use parameterised queries or an ORM for data access, with migrations (Flyway, Liquibase or EF Core) for the schema.
  4. Cover the cross-cutting parts: authentication with OAuth2/OIDC bearer tokens and an authorisation check per resource, cursor pagination for large or changing lists, an Idempotency-Key header on POSTs that clients retry, rate limiting, and versioning in the path or a header.
  5. Finish with how it gets shipped: unit tests on the service layer, integration tests against a real database (Testcontainers), structured logs with a request id, health endpoints, and a CI pipeline that builds, tests and deploys.

Follow-up

  • When would you use PATCH instead of PUT, and how do you stop a lost update when two clients edit the same resource (ETag with If-Match)?
  • A client times out on POST /payments and retries. How do you stop the payment being created twice?
  • How would you introduce a breaking change without breaking existing consumers?

For frontend/fullstack: How do you manage component lifecycles and state in React?

Medium · Technical and Stack-Specific

Approach

  1. Frame the lifecycle in hooks: a component renders, React commits to the DOM, then effects run. useEffect is for keeping in sync with something outside React, and its cleanup runs before the effect runs again and on unmount. The dependency array controls when it re-runs. Map the class methods onto this (componentDidMount, componentDidUpdate, componentWillUnmount) for older codebases.
  2. Place state by who needs it: useState or useReducer locally, lift it to the nearest common parent when siblings share it, use Context for values that change rarely (theme, current user), and use an external store (Redux Toolkit, Zustand) for complex shared client state.
  3. Keep server state separate from UI state: a library such as TanStack Query handles caching, deduplication, refetching and stale data, which removes most hand-written fetch-in-useEffect code.
  4. Do not store what you can compute. Derive values during render, and use useMemo only when the calculation is measurably expensive. Use keys to give list items a stable identity, and change a key when you want a component's state reset.
  5. Mention the traps: in React 18+ StrictMode, development mounts components twice (mount, unmount, mount) to expose missing cleanup. A fetch effect needs an AbortController or an ignore flag to avoid race conditions. Stale closures come from missing dependencies. Every consumer of a Context re-renders when its value changes, so split contexts or memoise the value.

Follow-up

  • A search box fires a fetch on every keystroke, and older responses sometimes overwrite newer ones. How do you fix it?
  • When would you choose useReducer over several useState calls?
  • A large list re-renders on every parent update. How do you find the cause and fix it?

For cloud roles: How would you design a secure, highly available architecture on GCP?

Medium · Technical and Stack-Specific

Approach

  1. Fix the requirements first: availability target, RPO and RTO, whether a zonal or a regional failure must be survived, data residency, and expected traffic. A single region spread across multiple zones covers most needs; multi-region costs more and is harder to keep consistent.
  2. Edge and compute: an external Application Load Balancer with Cloud Armor for WAF rules and DDoS protection, in front of Cloud Run (regional), a regional GKE cluster, or regional managed instance groups spread across zones, with health-check autohealing and autoscaling.
  3. Data: Cloud SQL configured for high availability (a standby in another zone, failover handled automatically), plus read replicas and a cross-region replica for disaster recovery. Spanner when multi-region strong consistency is required. Cloud Storage in a dual-region or multi-region location. Automated backups, with restores tested.
  4. Security: least-privilege IAM with a dedicated service account per workload, Workload Identity instead of exported keys, Secret Manager, private IPs for databases (private services access), VPC Service Controls around sensitive data, CMEK through Cloud KMS where compliance requires it, IAP for admin access, and organisation policies as guardrails.
  5. Operations: infrastructure as code (Terraform), CI/CD with canary or traffic-split releases (Cloud Run supports percentage traffic splits), Cloud Monitoring SLOs and alerts, uptime checks, centralised audit logs, and a failover runbook that is actually rehearsed.

Follow-up

  • Walk through exactly what happens to requests and writes when the zone holding the Cloud SQL primary fails.
  • How would you change the design to survive the loss of a whole region, and what does it cost in latency and consistency?
  • How do you stop a compromised workload from reading data it does not need?

One log partition stops advancing while the others drain

Easy · poison message · head-of-line blocking · consumer lag

Search results for a subset of tenants are hours stale; the rest are current. The projection consumer reports lag of zero on 15 of 16 partitions and 400,000 on one. Its error rate is flat and its CPU is idle. outbox_event has no pending rows older than a second, so the relay has published everything it holds. Identify the mechanism, give the ordered checks, and state what you do in the first ten minutes versus what you change permanently.

Approach

  1. Read the lag distribution first. A slow consumer lags everywhere; zero on fifteen partitions and 400,000 on one is not throughput. Idle CPU on the stuck partition means the consumer is not advancing its offset at all, which points at one message it cannot get past rather than at a rate problem.
  2. Exonerate the producer before touching the consumer. No pending outbox rows older than a second means the relay published, so the event exists in the log. This separates never sent from sent and never applied, which are different code paths and usually different owners.
  3. Read the message at the stuck offset and the handler's log lines for its event_id. A flat error rate with no progress has two explanations and you must distinguish them: the handler is throwing and the retry loop is swallowing it, or the handler is blocking on something and never returning. Idle CPU with no error lines favours the second.
  4. Mitigate before diagnosing further. Move the offending event to a dead-letter store and commit the offset past it. Adding consumers does nothing here, because a partition is consumed by exactly one member of the group, and the blast radius is every aggregate hashed to that partition, not only the aggregate that produced the bad event.

Follow-up

  • The dead-lettered event carried aggregate_version 7 and the projection had applied 6. What must the replay do differently if 8 and 9 landed in the meantime?
  • How do you show staleness to the user while the partition is behind, given the API already returns the projection's watermark?

Suggested practice checklist

The plan follows the three reported rounds: one day to map the loop and your stack, one for the recruiter conversation, three for the stack-specific questions candidates report, and two for client-facing behavioral stories.

Day 1 — Map the loop and choose your primary stack

  • Write the three reported rounds (HR Screening, Profile Matching, Technical Assessment) and, for each, what you must be ready to say or show.
  • Choose your primary stack from those candidates report (Java, .NET with React, Python, GCP) and list one project that proves it.
  • Collect certificates, diplomas and references so they are ready for the credential checks candidates report.

Deliverable: A one-page loop map, a chosen primary stack with its proof project, and a checklist of documents ready to send.

Day 2 — Rehearse the recruiter conversation

  • Write and speak your introduction and academic story, ending on the kind of project you want.
  • Write a competencies answer: primary stack, secondary stacks and one example each.
  • Research salary ranges for your stack and seniority, and set a target and a floor.
  • Write short answers on remote versus Lisbon hybrid and on the industries that motivate you.

Deliverable: A script card with five spoken answers (introduction, competencies, salary, remote or hybrid, motivating projects) and a written salary range.

Day 3 — Exception handling and debugging

  • Write your answer for your main language: the exception constructs, wrapping with the cause, cleanup, and one boundary handler that logs once.
  • Prepare one debugging story with the symptom, the sequence you followed, the fix and the regression test.

Deliverable: A written exception policy for your language, one debugging story and your notes from the practice exercise.

Day 4 — Databases and REST API fundamentals

  • Write a decision rule for relational versus non-relational databases with one example workload for each.
  • Outline a REST API build from scratch: resources, verbs, status codes, validation, persistence, authentication, tests and documentation.

Deliverable: A one-page database decision rule, a REST API build outline and your notes from the practice exercise.

Day 5 — React state and GCP availability

  • If your track includes React, explain component lifecycles with hooks and choose between local state, context and a store, with a small example.
  • If your track includes cloud, sketch a GCP architecture with regions, load balancing, IAM, encryption and backups, and write how it survives a zone failure.
  • If neither applies, spend the session on your own primary-stack question set instead.

Deliverable: A written React state explanation and a labelled GCP diagram with a short availability and security outline, or notes on your own stack.

Day 6 — Write client-facing behavioral stories

  • Write a disagreement story with the evidence you used and the outcome.
  • Write a tight-deadline story that shows scope cuts and communication.
  • Write a story about explaining a complex issue to a non-technical stakeholder using impact, options and recommendation.

Deliverable: Three written stories in a situation, decision, result format, each tagged with the other prompts it can answer.

Day 7 — Remote work, prioritization and a full run-through

  • Write your remote visibility routine with specific mechanisms for your manager and for a client team.
  • Write your prioritization method with one example of a tie-break between two urgent requests.
  • Do a spoken run-through of the recruiter questions and two behavioral stories, and revise the weakest answer.

Deliverable: A remote-work routine, a prioritization method and a recorded or spoken full run-through with the weakest answer revised.

Consulting-style behavioral preparation

Candidates report that the behavioral questions focus on the realities of project-based, remote consulting work: disagreements with seniors or clients, tight deadlines, staying aligned without being in the same room, explaining technical issues to non-technical people, and juggling urgent requests. Prepare real stories in which you made a decision, communicated clearly and can say what you would change.

  1. Tell me about a time you had to learn a new technology quickly to meet a project deadline.

Tell me about yourself and your academic trajectory.

Medium · HR, Background, and Motivation

Approach

  1. Use a chronological shape: where you studied and why, how you moved into software engineering, the last one or two roles with a concrete outcome each, and the kind of project you want next. A recruiter matching you to client work needs a clear timeline.
  2. For the academic part, name the degree, one project or thesis with real technical content, and any relevant certifications. Keep it to the parts that explain your current skills; do not recite every course.
  3. Make each role specific: the stack, your responsibility and one result you can verify. Weak: 'I worked on various backend services.' Stronger: 'I owned the Java order service and cut failed retries by moving to idempotent requests.'
  4. End by connecting to the opening: the stack you want, remote or hybrid preference if relevant, and why a project-based consulting setting suits you. The mistake that sinks this answer is a line-by-line CV reading with no destination.

Follow-up

  • Why did you choose that degree, and how did you end up in software engineering?
  • Which project from your studies or work would you most like to discuss in detail?
  • How does your background fit the kind of client projects you are looking for?

How do you handle exception management and debugging in [Java/Python/.NET]?

Medium · Technical and Stack-Specific

Approach

  1. Answer in the language you work in, with its real mechanisms. Java: checked versus unchecked exceptions, try-with-resources, a small custom hierarchy, wrapping with the cause. Python: specific excepts, context managers, finally, 'raise ... from e'. .NET: try/catch/finally, using blocks, 'when' filters, and 'throw;' rather than 'throw ex;' to keep the stack trace.
  2. State the policy, not only the syntax: catch where you can act, otherwise let it propagate to one boundary handler (a global handler or middleware) that logs once with context, returns a safe error to the caller and never swallows silently. Do not log secrets or personal data.
  3. Describe the debugging sequence: reproduce the failure, read the stack trace from the root cause upward, check logs and recent changes, narrow with breakpoints or bisecting, write a failing test, fix, then keep the test as a regression guard.
  4. Add the edge cases that show experience: async code (an unobserved failure in an async void method or an unawaited task/future), retries on non-idempotent operations, exceptions inside finally blocks, and production issues you debug through logs and traces because you cannot attach a debugger.
  5. Close with a short real example: the symptom, how you found the cause, the fix and what you changed to prevent it. The question is filed as behavioral, so a story makes it credible.

Follow-up

  • When would you use a checked exception, or a custom exception type, instead of a generic one?
  • How would you debug an error that only happens in production and that you cannot reproduce locally?
  • What is the difference between 'throw;' and 'throw ex;' in C#, or between returning an error and raising one in your language?

Tell me about a time you disagreed with a technical decision made by a senior team member or client. How did y

Medium · Behavioral and Consulting Fit

Tell me about a time you disagreed with a technical decision made by a senior team member or client. How did you handle it?

Approach

  1. Choose a real disagreement about a technical choice, such as a framework, schema, API shape or deployment approach, with a senior colleague or a client. Name the decision and your concern in concrete terms, and why it mattered for the project.
  2. Show how you made your case with evidence rather than opinion: a small prototype, a benchmark, a list of risks, or the cost of changing later. Say you raised it in the right place, usually first with your own lead or the person who made the call, with options instead of only an objection.
  3. Because Ankix places engineers with clients, say how you handled the client relationship: you stayed respectful, framed the concern as risk and options, and involved your project lead when the client owned the decision.
  4. State the outcome honestly. Either they changed course because of the evidence, or they kept their decision and you committed fully, documented the risk and monitored it. A story where you were simply right and everyone else was wrong is the mistake that sinks this answer.

Follow-up

  • What would you have done if they still insisted on their approach?
  • Looking back, was your concern correct, and how do you know?
  • How did the working relationship change afterwards?

Describe a situation where you had to deliver a project with very tight deadlines.

Medium · Behavioral and Consulting Fit

Approach

  1. Set the scene in two sentences: what was due, why the deadline was tight and what was at stake. Then spend the time on decisions, not on how hard you worked.
  2. Show scope control. Split the work into must-have, should-have and could-have, find the critical path, and agree the cut with the stakeholder instead of silently dropping things. Name what you cut and what you protected, such as tests on the core path and data safety.
  3. Show communication: you flagged risk as soon as you saw it, gave updated estimates, and kept a short written status so no one was surprised near the date.
  4. Cover the aftermath: the shortcuts you took, how you recorded them as follow-up tickets and whether you paid them back. Use only real numbers from the project. The mistake that sinks this answer is an overtime hero story with no scope negotiation and no mention of the risks you carried.

Follow-up

  • What exactly did you cut, and who agreed to it?
  • What technical debt did you take on, and how did you handle it later?
  • How did you tell the client or manager that the original scope was at risk?

How do you ensure your work is visible and you stay aligned with your team while working 100% remotely?

Medium · Behavioral and Consulting Fit

Approach

  1. Give mechanisms, not slogans. Examples: tickets that always show current status, a short written update at the end of each day or at stand-up, small pull requests that are easy to review, and decisions recorded in the tracker or wiki instead of a chat thread.
  2. Cover both audiences that candidates describe in remote consulting work: your own manager and colleagues, and the client's team. Say how each hears about progress and blockers, for example a weekly summary to the client lead and an early message to your manager when a dependency slips.
  3. Describe how you stay aligned: clarify working hours and response expectations at the start, join stand-ups and sprint planning prepared with an update, and move to a quick call when a written thread is going in circles.
  4. Show a concrete moment: a blocker you raised early, or a misunderstanding caught because your update was explicit. The mistake that sinks this answer is describing visibility as self-promotion rather than keeping the team informed and aligned.

Follow-up

  • What do you do when you are blocked and nobody answers?
  • How do you adapt when the client team uses different tools from your own team?
  • How would you notice that you and the team have drifted apart on what you are building?

Tell me about a time you had to explain a complex technical issue to a non-technical stakeholder.

Medium · Behavioral and Consulting Fit

Approach

  1. Pick an issue with a real consequence, such as a delayed release caused by a data migration, an outage root cause, or a performance problem. Give the situation briefly, then focus on how you explained it.
  2. Structure the explanation for the listener: start with the impact on the business or schedule, give the cause in one plain sentence (an analogy helps), present two or three options with cost, time and risk, make a recommendation, and say what decision you need from them.
  3. Show you avoided jargon without becoming inaccurate: you replaced terms such as 'race condition' or 'schema migration' with their effect on users or dates, and kept a precise version in writing for the engineers.
  4. Close with how you confirmed understanding, for example asking them to repeat the trade-off in their own words, and what they decided. The mistake that sinks this answer is a tour of the architecture, or over-simplifying so much that the stakeholder makes a decision on false information.

Follow-up

  • How did you check that they understood the trade-offs?
  • What did you do when the stakeholder asked for a date you could not guarantee?
  • How would you have explained it to a different audience, such as the client's CTO?

How do you prioritize your tasks when dealing with multiple urgent requests?

Medium · Behavioral and Consulting Fit

Approach

  1. Show a repeatable method. List every request, clarify the real deadline, who is affected and the cost of delay, then rank: production incidents and blockers for others first, then work with a fixed date, then everything else.
  2. Name the consulting-specific trap: two stakeholders each call their item top priority. Say you put the conflict in front of the project lead or the people who own priorities, with a short note of the options and dates, instead of deciding silently.
  3. Explain how you communicate: tell requesters what moves and the new expected date, so nobody discovers a delay later. Mention protecting focus time and recording the decision in the tracker.
  4. Give a short example with a real tie-break, such as a bug in production during sprint work, and what you postponed. The mistake that sinks this answer is saying you do everything at once, or ranking by whoever pushes hardest.

Follow-up

  • What do you do when two senior people each insist their request is first?
  • A production bug arrives mid-sprint. What happens to the sprint work?
  • How do you say no or not yet without damaging the relationship?