Abnormal AI · Software Engineer
Updated · 2026-09-24

Abnormal AI Software Engineer
Interview Guide

THE 60-SECOND BRIEF

A Software Engineer at Abnormal AI is responsible for building and scaling the next generation of AI-driven cybersecurity platforms. The primary mission of this role is to safeguard enterprise communications—including email, SaaS applications, and cloud infrastructure—against highly sophisticated, socially engineered cyber attacks. This requires designing and implementing real-time detection pipelines, high-throughput data processing systems, and user-facing applications that integrate seamlessly with state-of-the-art machine learning models.

The title spans product, platform and infrastructure work, and which of those the seat actually is decides whether design or algorithms carries more weight in your preparation. The posting rarely settles it; what the team is on call for usually does.

Abnormal AI candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.

Build at-least-once pipelines with explicit deduplication horizonsBound blast radius with per-tenant concurrency limitsScope every query and cache key by tenant

41 min read

Practice 15 Software Engineer prompts
1Company bank questionsSnapshot · Sep 25, 2026 PT
3Candidate experiences ↗Read their reports
15Practice promptsAcross five skill areas
3With worked solutionsIncluded in the practice prompts

A Software Engineer at Abnormal AI is responsible for building and scaling the next generation of AI-driven cybersecurity platforms. The primary mission of this role is to safeguard enterprise communications—including email, SaaS applications, and cloud infrastructure—against highly sophisticated, socially engineered cyber attacks. This requires designing and implementing real-time detection pipelines, high-throughput data processing systems, and user-facing applications that integrate seamlessly with state-of-the-art machine learning models.

The impact of a Software Engineer at Abnormal AI is immediate and highly visible. You will work on a platform that processes massive volumes of data daily, analyzing complex behavioral signals to block malicious activity before it reaches the end user. Whether you are optimizing a high-performance backend service, building scalable data pipelines using technologies like Apache Spark, or developing intuitive frontend interfaces in React.js, your work directly contributes to the core defense mechanisms of thousands of global enterprises.

What makes this role exceptionally unique and challenging is the company's aggressive focus on AI-assisted development. Abnormal AI does not just build AI products; they expect their engineering team to operate at a 10x execution speed by deeply integrating AI tools like Cursor and ChatGPT into their daily coding workflows. As a Software Engineer, you will be expected to demonstrate high technical ownership, low ego, and a forward-looking approach to software craftsmanship in a rapid, high-growth startup environment.

01

Recruiter Screen

reported

Before anything technical happens, someone has to decide which rung of the ladder your loop is calibrated to, and that decision sets the bar for every round after it. It comes from how you describe scope, not from your title, because titles do not convert cleanly between companies. The weak version of the answer is team size and years. The strong version names the largest change you shipped where nobody reviewed the design, what would have broken if you had been wrong, and what you were paged for. Get the level said out loud on this call, because the range and the loop both follow from it.

What to demonstrate

  • Whether the scope in your own account maps onto a level the team actually has an opening at, so a mismatch ends the process cheaply rather than after four interviewers have spent a day
  • Whether your title needs re-mapping: the same word describes very different amounts of independent decision-making at a twenty-person company and a ten-thousand-person one
  • Whether your compensation expectation can be filled at that level in the structure the role pays in, which is why the number gets asked for before any engineer is scheduled

How to prepare

  • Write down two changes from the last two years: the largest one you designed with nobody reviewing the design, and the largest one where someone more senior did. Lead with the first when scope comes up, and be ready to say which parts of the second were yours
  • Ask which level the loop is calibrated to and what changes at the level above it, then plan your weeks from that answer rather than from the posting
  • Settle a total-compensation range beforehand with the split named, base against bonus against equity and its vesting period, so a question about numbers gets a number instead of the word market
PracHub interview research ↗
02

Hiring Manager Discussion

reported

The design portion here is shorter and lower-stakes than a dedicated design round, which changes what it tests. There is rarely time to reach a full component diagram, so what gets read is your first two minutes: whether you pin down constraints, meaning request rate, data size, what must not be lost and how stale a read may be, before naming any technology. Opening with a stack list invites being steered back. Once the numbers are on the table, say what breaks first if they grow tenfold, and defend the plain option where the load does not justify more.

What to demonstrate

  • Whether constraints come before components: peak request rate, data volume, what must survive a process dying, and the staleness the product can tolerate
  • Whether you can name what saturates first when traffic grows by an order of magnitude, and whether that matches the design you just sketched
  • Whether a cache is reasoned about on both paths, since a cold or recently flushed cache sends the full request rate to the origin, so capacity has to cover the miss case and not only the steady state
  • Whether you distinguish what you have operated from what you have only read about, which usually shows up in the answer to why a particular component is there

How to prepare

  • Take one system you worked on and write down the numbers you would need to defend it: requests per second at peak, rows in the largest table, the latency you were actually held to. Not having them is the common stall in this part.
  • Practise the tenfold question on that system out loud, naming the first bottleneck you would hit, whether that is a single writer, connection limits, disk, or a queue that grows faster than it drains, and the smallest change that buys headroom.
  • Prepare one decision where the plain option was correct: the cache you did not add or the queue you did not introduce, with the load figure that made that the right call. Being able to argue for less is rarer than being able to argue for more.
PracHub interview research ↗
03

Technical Assessments

reported

Input bounds are the part of the prompt most often skimmed, and they usually contain the answer. They tell you which complexity class is admissible, which narrows the search before you have thought about the problem itself. As a rough planning figure, a compiled language does on the order of 10^8 simple operations per second and an interpreted one roughly an order of magnitude less. So n up to about twenty admits enumerating subsets, a few thousand admits a quadratic pass, and a million admits neither: you need near-linear, or linear with a log factor. If the bounds are missing, ask for them.

What to demonstrate

  • Whether the approach is justified by the stated input size rather than by whichever pattern you recognised first
  • Whether you ask about the properties that change the algorithm: whether the input arrives sorted, whether duplicates occur, whether values are bounded integers, whether it all fits in memory
  • Whether you can name the bottleneck in your own solution and what would remove it, even when you deliberately leave it in place
  • Whether a claimed speedup is real, since memoising a recursion only helps when subproblems genuinely overlap and the state can be keyed cheaply

How to prepare

  • For each algorithm you rely on, write down the largest n it handles in roughly a second, then check two of those figures by timing them in the language you will actually type in
  • For two weeks, write one line naming your target complexity and the bound that justifies it before you write any code, then compare that line with what you ended up submitting
  • Practise the conversion backwards: given a required O(n log n), list the mechanisms that get you there (sorting, a heap, an ordered map, divide and conquer) and choose by what the problem needs to query, not by what you used last
PracHub interview research ↗
04

Interactive Pair-Programming

reported

An unlabelled round is first an information problem, and the cheapest information is free. Whoever schedules it can usually tell you how long it runs, who will be in the room and what they work on, whether you will be writing code and in what environment, and whether anything is being sent beforehand. Ask in writing so the answer is on record, then prepare for the two or three formats those answers still leave open instead of betting on one. What separates a strong candidate is not guessing right; it is having an opening that works whichever one it turns out to be.

What to demonstrate

  • Whether you can start work from an ambiguous brief, since tolerating a vague scope without stalling is the same thing the job asks for
  • Whether the questions you asked beforehand were ones that change your preparation, such as duration, medium and who is joining, rather than ones whose answers you could not have acted on
  • Whether you adapt when the round turns out to be something other than what you were told, instead of spending the first ten minutes visibly recalibrating

How to prepare

  • Send one short scheduling message asking four things: how long, who is joining and what they work on, whether you will be writing code and where, and whether to prepare anything in advance. Treat a vague reply as real information, since it means the round is loosely structured and you will be shaping it yourself.
  • Write one opening that works in any of the formats still open: restate in your own words what you have been asked to do, then ask which of two directions is more useful to them. Say it aloud until it stops sounding recited.
  • Set up for the two most likely formats before the call starts, with a blank editor in the language you would choose and a shared document you can type into, so a format surprise costs you nothing in the first minutes
PracHub interview research ↗

3 candidate reports. Individual accounts describe a particular role and hiring cycle.

Software Engineer

Abnormal AI Software Engineer interview: feature implementation in an existing codebase

Technical Screen

My technical interview focused on AI-assisted coding. I was placed in a fairly large existing codebase and first had to make sense of it with AI tools. Then I used that understanding and AI support to implement a feature and write tests for the changes. It felt less like a pure algorithm check and more like a test of whether I could turn a task into working code while using AI in a controlled way…

Read full experience
Software Engineer

Abnormal AI Software Engineer interview: AI agents used throughout a real-work loop

HR Screen → Technical Screen → Other

After a recruiter call, I met a hiring manager to discuss my background, projects, and what I hoped to learn from the team. Everyone was welcoming and responsive, and the handoffs between rounds were clear. The technical work centered on AI rather than classic LeetCode prompts. In a large codebase, I used AI to understand the structure, implemented a feature with AI assistance, and wrote tests. T…

Read full experience

PracHub editorial advice for the preparation topics above.

01

Serialising a tenant's writes through select ... for update on a single counter row

It is the first change that makes a counter correct, and it caps that tenant's write throughput at roughly one divided by the lock hold time. A transaction that takes the lock, makes a network call and then commits holds it for the entire round trip: at 2 ms that is about 500 writes per second for the whole tenant, and the largest tenants are exactly the ones that exceed it. The damage then spreads, because every waiter holds a database connection while it queues, so one hot tenant drains the shared pool and the symptom presents as a site-wide latency incident rather than as a lock problem. The repairs are to shrink the critical section to a single statement, to shard the counter into per-(tenant, hour) or per-(tenant, bucket) rows and sum on read, or to batch in memory and flush periodically while accepting the bounded loss that batching implies.

02

Paginating a growing table with limit and offset

Two unrelated defects share the idiom. Correctness: rows inserted or deleted between page requests shift the window, so a consumer walking an export skips rows and sees others twice, which for a customer-facing sync is silent data loss rather than an error anyone notices. Cost: the database still produces and discards the skipped rows, so page N costs time proportional to N times the page size and a deep page on a large table degrades from milliseconds to seconds. Keyset pagination over a stable, unique, indexed ordering -- where (created_at, id) < ($1, $2) order by created_at desc, id desc limit $3 -- is constant-cost per page and immune to shifting, on the precondition that the cursor columns never change value for a row, which disqualifies updated_at as a cursor.

03

Trusting input because it came from your own front end

Anything crossing a trust boundary is hostile: parameterise queries instead of building SQL by concatenation, validate against an allow-list rather than a deny-list, and bound the size of anything you allocate from a request. Raising this unprompted in an API or design question is a cheap and unusually strong signal.

04

Assuming the bug is in the framework

Suspect your own code first: read the stack trace top to bottom, check which versions are actually installed rather than which ones you believe are, and reproduce in isolation before blaming a library that thousands of people run daily. When the fault really is upstream, you need that minimal reproduction to say so credibly anyway.

Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.

12 technical prompts3 include a worked solution

Build a secure file storage vault application with backend and fronten…

medium
data structures and algorithms

Build a secure file storage vault application with backend and frontend components. Explain how you prompted your AI tool to generate the boilerplate and handle file encryption.

Approach
  1. State the target complexity and say which constraint rules the naive version out.
  2. Choose the data structure from the access pattern, not from familiarity.
  3. Name the brute-force solution and its complexity before improving on it.
Follow-up
  • How does this change if the input no longer fits in memory?
  • Which test case would catch an off-by-one here?

Implement a rate-limiting middleware for an API endpoint. Show how you…

medium
data structures and algorithms

Implement a rate-limiting middleware for an API endpoint. Show how you use an AI assistant to write unit tests that cover edge cases like concurrent requests and token bucket exhaustion.

Approach
  1. Name the brute-force solution and its complexity before improving on it.
  2. State the target complexity and say which constraint rules the naive version out.
  3. Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
  • What is the worst case, and how likely is it on real data?
  • Which test case would catch an off-by-one here?

Parse and verify a timestamped multi-signature webhook header

easyWorked solution
parsinghmacconstant-time-comparereplay-protection

An inbound webhook carries a signature header of at most 1 KiB shaped t=<unix seconds>,v1=<64 hex chars>, with up to five v1 values during secret rotation and possibly unknown scheme keys. You hold the raw request body bytes and the currently active signing secrets. Write the parser and the verifier: accept when any active secret reproduces a signature and the timestamp is within a five-minute tolerance in either direction, reject otherwise. Single left-to-right pass over the header, no regular expression. State what is inside the MAC and why.

Approach
  1. Parse in one scan: split on ,, then on the first = only, since a value may itself contain = under a future scheme. Accept t exactly once and treat a second t as a reject rather than last-wins. Push every v1 onto a short list and ignore any other key, so a v2 can be introduced later without breaking this verifier.
  2. Say what is signed: HMAC-SHA256 over the exact byte string <t>.<raw body bytes>, yielding 32 bytes or 64 hex characters. The timestamp sits inside the MAC because otherwise an attacker replays yesterday's body with its still-valid signature and only has to edit the header timestamp.
  3. Hash the bytes as received. Verifying against a re-serialised JSON body is the usual defect: key order, whitespace and number formatting all change the bytes while the parsed objects compare equal, so signatures fail for honest senders and the popular 'fix' is to stop checking.
  4. Compare in constant time over fixed-length digests. Decode the hex to 32 bytes, accumulate acc |= a[i] ^ b[i] across the whole length, and test acc == 0 at the end. Evaluate every candidate without an early exit; at five candidates that is five HMACs over the body, linear in body size and negligible beside the network.
  5. Apply the tolerance as a two-sided bound, rejecting when |now - t| > 300 seconds. A sender whose clock runs ahead of yours is an ordinary case, and an unbounded future timestamp is a free replay window.
  6. Complexity: O(L) over the header producing k candidates, plus k HMACs at O(|body|) each. Space is O(k) beyond the body itself. Do the cheap rejections, including the tolerance check, before any cryptography runs.
Worked solution 15 min
  1. Write the grammar on one line before coding: header := field (',' field)*, field := key '=' value, split on the first = only.
  2. Implement the parser to return {t: int, v1: [hex, ...]}, rejecting a missing t, a duplicate t, any v1 that is not 64 hex characters, and a header over 1 KiB, all before any cryptography runs.
  3. Implement the verifier: for each active secret compute HMAC-SHA256(secret, f'{t}.'.encode() + raw_body), compare it in constant time against each parsed v1, and OR the results with no early exit.
  4. Test with a valid signature; the same body with t moved 400 seconds into the past; the same body with t 400 seconds into the future; a header carrying an unknown v2= alongside a valid v1; and a body re-serialised with different JSON key order.
EXPECTED RESULTThe valid case accepts. Both out-of-tolerance cases reject, including the future one. The unknown `v2` field is ignored and the `v1` still verifies. The re-serialised body fails, which is correct and is exactly why the raw bytes must be retained.
Follow-up
  • The body is 40 MB. What changes about where you verify, and what can you do before the whole body has arrived?
  • A customer reports that signatures fail for exactly the requests whose body contains a non-ASCII character. What is your first hypothesis?
  • How do you rotate the signing secret with no failed deliveries, and how long do both secrets stay live?

For a candidate senior enough that the loop turns on design and judgement rather than on whether the coding round gets finished. Five days build one system properly and then stress it; coding gets a single maintenance day, on the assumption that the risk at this level is an unexamined tradeoff rather than a missed algorithm.

Small steps. Visible outcomes.0 / 7 completed
ONE WEEK · YOUR PACE

Prepare, practise & reflect

One practical outcome each day. Spend longer where you need it.

0 / 7 done
01Numbers before diagrams
  • Build your own reference card of the figures you will re-derive all week: bytes for a realistic record, requests per second implied by a given daily active count, and the storage that a year at a given write rate produces. Derive each one rather than copying it, because the derivation is what survives a follow-up.
  • Turn one product statement into capacity requirements. From ten million daily users at four writes and forty reads each, state the peak-to-average factor you are assuming and why, then produce peak write QPS, peak read QPS and a year of storage.
  • Write the two numbers whose order of magnitude changes the design, the read-to-write ratio and the working-set size against memory per node, and state the threshold at which each one flips your answer.

Deliverable: A one-page numbers card and one worked capacity estimate with every assumption written down.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗
02One system, from requirements to schema
  • Spend the first ten minutes producing only functional requirements, non-functional targets with numbers attached, a p99 latency, a durability expectation, a consistency requirement, and an explicit out-of-scope list.
  • Define the interface before the boxes: the three or four endpoints, their parameters, what each returns, and which of them are idempotent.
  • Write the data model, then write the single access pattern that justifies it, and state what the schema would have to become if the dominant access pattern were the other one.

Deliverable: One design carried to endpoint-and-schema depth, with non-functional targets expressed as numbers and a written out-of-scope list.

Practice prompt ↗Practice prompt ↗
03The consistency you are actually buying
  • Write out what a client sees under asynchronous replication when its write commits on the leader and its next read is served by a lagging follower, then write the two fixes, pinning that session's reads to the leader for a bounded window or carrying a version token the replica must reach, and the cost of each.
  • Work the quorum arithmetic on paper for N of three with W and R of two, and separate what R + W > N does guarantee, that any read set intersects any write set, from what it does not: on its own it is not linearizability, and a sloppy quorum that accepts writes on nodes outside the preference list breaks even the intersection.
  • Take two storage choices with different defaults, a single-leader relational store committing synchronously and a quorum-replicated store that converges eventually, and write the specific product behaviour that would be wrong under each, rather than a general statement about which is stronger.

Deliverable: A page separating what quorum overlap guarantees from what it does not, with one concrete product misbehaviour attached to each gap.

Practice prompt ↗Practice prompt ↗
04Failure is the design
  • For one write path, work through the case where the client times out after the server has already committed, then design the idempotency key: who generates it, how long it is retained, and what the duplicate request returns.
  • Express the retry policy as parameters rather than as a word: maximum attempts, base delay, backoff factor, jitter, and which error classes are retried at all. Then state why retrying a non-idempotent write without a key is a correctness bug and not merely waste.
  • Compute the fan-out effect on tail latency. If a request waits on ten backends and each independently exceeds its p99 one percent of the time, the chance at least one is slow is 1 - 0.99^10, about ten percent. Then write why independence is the optimistic assumption and what correlates them in practice.
  • Name the backpressure mechanism for one queue or one dependency in the design, a bounded queue with shedding or a concurrency limit, and write what the caller is told when it engages.

Deliverable: One write path with an idempotency design, a parameterised retry policy, and a written tail-latency calculation with its assumption named.

Practice prompt ↗Practice prompt ↗Worked solution ↗
05Scaling the hot path
  • Choose cache-aside or write-through for one read path and write the staleness window each produces, then name the invalidation event and what the system does when that event is lost.
  • Design against the stampede: either coalesce requests so only one recomputes a missing key, or refresh early with jittered expiry, and write why identical TTLs on keys populated in the same moment produce a synchronised expiry and a thundering herd.
  • Shard one table by a key you choose, then answer the two questions that break the choice: which queries now require a scatter-gather, and what happens to the distribution when one tenant is a hundred times larger than the median.
  • Write the cost of adding a node under plain modulo placement, where nearly every key moves, against consistent hashing, where roughly one key in n+1 moves, and state what virtual nodes are for.

Deliverable: A caching and sharding decision for one path, each with its failure mode and its rebalancing cost written beside it.

Practice prompt ↗Practice prompt ↗
06Keep the coding hand in, at the bar that applies to you
  • Solve one medium problem in thirty minutes, then spend twenty more making it production-shaped: named invariants, validation at the boundary, and errors that distinguish a caller mistake from an internal fault.
  • Write the tests you would require of a colleague's version of that function: one for empty input, one for the boundary, and one for the case the implementation is most likely to get wrong.
  • Read a piece of your own code from six months ago and write the change you would ask for, phrased as you would actually phrase it in review.

Deliverable: One problem hardened to review standard, with its test list and one written review comment.

Practice prompt ↗Practice prompt ↗
07Defend it while being interrupted
  • Run a forty-five-minute design mock with an interviewer briefed to change a requirement halfway, a tenfold traffic increase or a new strict consistency requirement, and to push on one number you estimated.
  • Rehearse the two sentences a senior loop is listening for: naming the tradeoff you are choosing against and why, and saying what you would measure to learn that the choice was wrong.
  • Prepare the design you regret: a real decision, the constraint that produced it, what it cost, and what you changed afterwards.

Deliverable: Mock notes recording how the design changed under the new requirement, plus a written account of one regretted decision.

Practice prompt ↗Practice prompt ↗Worked solution ↗

Expand any day for tasks and deliverables. Your progress is saved on this device.

Bring the two or three numbers the story rests on and know how they were collected. A p99 whose timer starts inside your handler excludes the time a request spent queued, so it can sit flat while users wait longer. Give the window, the percentile and what the measurement left out, or drop the number.

Given a boilerplate codebase, add an integration that pulls data from …

medium
behavioural and engineering judgement

Given a boilerplate codebase, add an integration that pulls data from a third-party security API. How do you handle API throttling and credential rotation?

Approach
  1. State the situation in two sentences and spend the rest on the reasoning.
  2. Give the blast radius: what could have broken, and what you measured.
  3. Pick a story where you made the decision, not one where you watched it.
Follow-up
  • How did you know your change caused the improvement?
  • What would you do differently if you ran that again?

Resolve a review disagreement over a quota check

easy
code reviewisolation levelswrite skewdisagreement

A colleague's pull request enforces a per-tenant quota by selecting the current count and then inserting when it is under the limit. You flag it as a race. They reply that the transaction already runs at repeatable read, so the snapshot makes it safe, and the tests pass. Walk through taking that disagreement to a resolution: what you write in the review, what you demonstrate rather than assert, which fix you propose and why, and what you do if they still disagree after all of it.

Approach
  1. Answer the claim precisely instead of restating your objection, because they have made a specific technical argument. In PostgreSQL, repeatable read is snapshot isolation; this is write skew, which snapshot isolation permits by design. Both transactions read a count that is stable within their own snapshot, insert disjoint rows that the other cannot see, and both commit, so the limit is exceeded by exactly the concurrency.
  2. Demonstrate rather than cite. Two psql sessions, both BEGIN ISOLATION LEVEL REPEATABLE READ, both select the count, both insert, both commit: it succeeds. Repeat at SERIALIZABLE and the second commit fails with serialization_failure, SQLSTATE 40001. That takes two minutes, ends the argument without anyone conceding a position, and leaves an artefact for the next reviewer.
  3. Offer the options with their costs rather than a verdict. Serialisable plus a retry loop on 40001 is correct but obliges every caller to retry and degrades under contention. An increment-and-compare on a counter row — update tenant_quota set used = used + 1 where tenant_id = $1 and used < limit returning used — is safe even at read committed, because a blocked updater re-evaluates the WHERE clause against the row version it finally locks, and zero rows returned means full. A unique or exclusion constraint that makes the surplus write fail is the third.
  4. Name the plausible non-fix explicitly, since it is what usually gets merged instead: folding the count into the insert as insert ... select ... where (select count(*) ...) < limit is still racy under read committed, because the subquery cannot see the other transaction's uncommitted rows. It looks atomic and is not.
  5. Say what you do if they still disagree: escalate the decision rather than the disagreement. Attach the reproduction, hand it to the service owner or a third reviewer, and state that you will not block the merge if the owner accepts the risk knowingly — and that you want that acceptance written down.
  6. Close with the general lesson worth leaving in the review thread: a passing suite is weak evidence for a concurrency claim because it runs one request at a time. Ask for a test that runs two.
Follow-up
  • Write the counter-row version. Does your answer change if the quota counts child rows rather than a column?
  • Under serialisable, who performs the retry, and what does the API client see if the retry also fails?
  • This is the third disagreement with the same reviewer this month. What changes in how you review?

Estimate a tenant-leading index migration you have never run

hard
estimationonline migrationindex buildsuncertainty

Someone needs a date. usage_event carries an index on (occurred_at) and needs (tenant_id, occurred_at); the largest tenant holds roughly a hundred times the median tenant's rows, the table is partitioned daily with years of retention, and you have never run a migration on a table this large. Give an estimate you would defend: how you decompose the work, the two or three numbers you would go and measure first, the range and confidence you state, and what you commit to when the person asking needs a single date today.

Approach
  1. Refuse the bare number and then give one anyway, in the form that is actually useful: a range plus the measurement that collapses it. 'Four to eleven days; one afternoon building this index on a restored copy of the largest partition takes that to within a day' is an answer, while 'it depends' is not.
  2. Decompose by failure mode rather than into equal chunks, because that is where estimates go wrong. On a partitioned parent you create the index ON ONLY the parent, build each partition's index with CREATE INDEX CONCURRENTLY, then ALTER INDEX ... ATTACH PARTITION, at which point the parent index becomes valid. CONCURRENTLY does not block writes but scans each partition twice, waits out older transactions, cannot run inside a transaction block, and on failure leaves an invalid index you must drop concurrently and retry.
  3. Name the two unknowns that dominate and price them: build time on one restored partition of realistic size, and whether the planner actually chooses the new index for the skewed tenant, since selectivity for a tenant holding most of the rows is a different question from selectivity for the median tenant. Both are half-day measurements against a replica, and both are cheaper than being wrong by a week.
  4. State the assumptions the range is conditional on, because that is what makes a slip a re-estimate instead of a credibility event: no partition above a stated row count, one concurrent build at a time so it does not compete with ingest for I/O, and an ingest backlog that can absorb the added write amplification while both indexes exist.
  5. Budget the step nobody budgets: verification and the old index's removal. Dropping the old index is fast, but deciding it is safe to drop means confirming no plan still uses it, and that confirmation waits on real traffic across a full weekly cycle rather than on your patience.
  6. Answer the single-date request honestly. Commit to a date for the first checkpoint — the measured build number from the replica — and to re-estimating on that date, and say plainly what you are not committing to yet. A date with a scheduled re-estimate is worth more to the asker than a confident wrong one, and you should say why in those words.
Follow-up
  • The concurrent build fails half way through the largest partition. What is the state of the database and what do you do next?
  • Your estimate slips by sixty percent. Which assumption broke, and at what point would you have known?
  • The person asking needs the date for a customer commitment. Does your answer change?
  • 01

    Given a boilerplate codebase, add an integration that pulls data from a third-party security API. How do you handle API throttling and credential rotation?

  • 02

    A colleague's pull request enforces a per-tenant quota by selecting the current count and then inserting when it is under the limit. You flag it as a race. They reply that the transaction already runs at repeatable read, so the snapshot makes it safe, and the tests pass. Walk through taking that disagreement to a resolution: what you write in the review, what you demonstrate rather than assert, which fix you propose and why, and what you do if they still disagree after all of it.

  • 03

    Someone needs a date. usage_event carries an index on (occurred_at) and needs (tenant_id, occurred_at); the largest tenant holds roughly a hundred times the median tenant's rows, the table is partitioned daily with years of retention, and you have never run a migration on a table this large. Give an estimate you would defend: how you decompose the work, the two or three numbers you would go and measure first, the range and confidence you state, and what you commit to when the person asking needs a single date today.

PracHub interview preparation framework ↗
Is this an official Abnormal AI interview guide?

No. It is PracHub's own research and practice material for the Software Engineer role at Abnormal AI. Rounds and questions reflect what candidates have reported, not a process Abnormal AI has published, and they change over time. Confirm the current format and scope with your recruiter.

PracHub interview research ↗
How heavily is AI integrated into the interview process?

Extremely heavily. Unlike traditional tech companies that ban or discourage the use of AI during interviews, Abnormal AI actively embraces it. You will be expected to use tools like Cursor during both your take-home assignment and live coding rounds. You will be evaluated on your "AI leverage"—how effectively and quickly you can prompt, debug, and build applications with AI assistance.

PracHub interview research ↗
Do I need to be an expert in cybersecurity to apply?

No. While prior experience in cybersecurity or machine learning is a nice-to-have, Abnormal AI prioritizes strong software engineering fundamentals, system design capabilities, and a high-velocity execution mindset. You will have ample opportunity to learn the security domain on the job.

PracHub interview research ↗
What is the typical timeline from the initial recruiter screen to a final offer?

The process is designed to be highly efficient and typically wraps up within three to four weeks. However, because the process involves intensive practical rounds (including a take-home assignment), the actual speed depends heavily on how quickly you can complete the take-home task and schedule your follow-up panels.

PracHub interview research ↗
What is the hybrid/remote work policy at Abnormal AI?

Abnormal AI operates on a hybrid model with physical offices in key hubs like San Francisco, Bengaluru, Singapore, and London. Candidates are typically expected to work from their local office a few days a week to foster close collaboration, though specific team arrangements may vary.

PracHub interview research ↗
Sources & methodology 3 sources ↗

Official role evidence, timestamped platform data and clearly labeled preparation advice.