The Software Engineer role at Okta spans three areas: internal platforms that improve developer productivity, scalable authentication services, and GenAI integrated into business workflows, including virtual agents and RAG-based search. The code affects how organizations manage access and identity, and engineers work with product, data science and security. Be ready to show distributed-systems work in the language you know best, with the trade-offs you made stated plainly.
The reported questions match that mix. On the coding side, candidates describe a breadth-first search over a weighted map, finding the index that breaks an alternating parity pattern, a memory allocator with alloc and erase-by-ID operations, the minimum height difference between two peaks under a distance constraint, and flattening a complex JSON input to compute a weighted average. On the design side: an IP banlist shared across every system in a company, an architecture for high concurrency and rate limiting, a schema for a scalable service, and the end-to-end data flow of a feature through databases and message queues.
Behavioral prompts cover difficult technical trade-offs, mentoring a peer or taking a project from prototype to production, disagreeing with a teammate's approach, and your experience with user lifecycle management or identity and access management. Because a reported behavioral prompt asks about identity and access management, refresh SAML and OAuth fundamentals before the loop.
Recruiter Screening
reportedCandidates describe this as a recruiter call about your background and fit for the role. Use it to find out which kind of Software Engineer seat you are interviewing for. The role ranges from internal developer-productivity platforms to authentication services to GenAI integrations, and each calls for different preparation. Ask what the team builds and operates, which language it works in, and which platform any coding assessment runs on, because some assessments are reported as timed and proctored on a third-party platform. Then say plainly which parts of the posting you have done and which you have not.
What to demonstrate
- Whether your background maps honestly onto the posting, including the requirements you have not met yet
- Whether you can summarise distributed-systems or cloud-native work you shipped in one sentence each, with your own part and the scale stated
- Whether what you want next fits the seat, for example platform work versus authentication services versus GenAI tooling
How to prepare
- Mark every line of the posting as done, adjacent or new, and write one sentence for each adjacent line naming the closest thing you actually built
- Prepare a two-sentence answer on identity work you have touched, such as login, sessions, role checks or offboarding, because a reported behavioral prompt asks about user lifecycle or identity and access management
- Write down three questions for the recruiter: what the team is responsible for, which language it uses, and which assessment platform and editor you will be using
Technical Assessments
reportedCandidates describe this stage as a series of coding rounds and system design discussions. The reported coding questions for the role are not assigned to a specific round. They lean on graph search (BFS over a weighted map), linear array scans (an alternating parity break), ordered-set lookups (the closest heights between two peaks under a distance constraint), stateful simulation (alloc and erase-by-ID memory management) and parsing (flattening JSON to compute a weighted average). Most time in this format goes to a half-remembered library call or random edits to a failing solution, not to thinking. When output is wrong, take the smallest failing input and trace the state by hand before you change anything.
What to demonstrate
- Whether you pick the right algorithm for the stated input, such as Dijkstra instead of plain BFS once edge weights differ
- Whether edge cases are named before coding: an empty input, negative numbers in a parity check, zero total weight in an average, an allocation that does not fit
- Whether a failing case is isolated and explained before any edit is made
- Whether a design discussion starts from requirements and traffic shape, not from a diagram you brought with you
How to prepare
- From an empty file, in the language you write fastest, implement Dijkstra with a min-heap and a multi-source BFS, then an alloc x / erase ID simulator. The report names only those two operations, so first write down the contract you assume (for example, what alloc returns on failure) and practise confirming it with the interviewer
- Write the parity check with a bitwise test (x & 1) and explain why x % 2 == 1 misses negative odd numbers in Java and C++, where -3 % 2 is -1
- If the assessment runs on a proctored third-party platform, solve at least one timed problem in that platform's editor beforehand so the tooling is not new on the day
Deep-Dive Interviews
reportedCandidates describe these as interviews with team members and management that assess both technical competence and cultural alignment. Expect to walk through past projects in detail: the technical challenges you faced and the impact of your specific work. Prepare three projects, each rehearsed until you can handle a follow-up you did not expect. Specific details separate a real answer from filler. Give every number its definition: a p99 is measured over some window at some hop, and a server-side figure leaves out the queueing and network time a client sees. If you cannot qualify a number, leave it out.
What to demonstrate
- Whether your examples carry detail only someone who did the work would know: the binding constraint, the alternative you rejected and why it was worse, and what you measured before and after
- Whether a number holds up to a follow-up about what it measured and whether your change caused it
- Whether your part in a team effort is stated accurately, including what other people did
- Whether you can explain a design decision to a manager in terms of risk and cost as well as to an engineer in terms of mechanism
How to prepare
- Write a page on each of three projects covering the constraint, the rejected option, the measurement before and after, and what went wrong, and cut every line you cannot defend under a follow-up
- Recover real figures while you still can (request volume, data size, latency with its percentile and window, team size) and mark which ones are estimates
- Pick one project that involved distributed systems, APIs or access control, and rehearse the security implications of its interfaces, since reported evaluation areas include the security of an API implementation
Behavioral Assessments
reportedCandidates describe this stage as an evaluation of behavioral fit with the team. The reported behavioral questions for the role are not tied to a specific round: they cover a difficult technical trade-off and how you justified it, mentoring a peer or leading a project from prototype to production, disagreeing with a teammate's technical approach, and experience with user lifecycle or identity and access management. Your first answer mostly earns the follow-ups, and the follow-ups decide how the story is judged. Know four or five pieces of work down to the code you changed and the argument you had about it, rather than preparing one shallow story per prompt.
What to demonstrate
- Whether a story holds as questioning moves from what you did to why you chose it over the alternative, and then to what you would change now
- Whether you answer the question actually asked, not a rehearsed block that answers a nearby one
- Whether a trade-off story names both options, the cost you accepted and how you would have known if the choice was wrong
- Whether a mentoring or prototype-to-production story shows what the other person or the system could do afterwards that it could not before
How to prepare
- Take four projects and write the chain four levels deep: what you did, why, why not the alternative, and what would have had to be true for the alternative to win. Any project you cannot take to the fourth level is not ready yet
- Map each reported behavioral question to one of those projects on a single page, so the choice of story is already made before the interview
- Have someone ask why three times on one thread, and mark where you start repeating yourself; that is the part to rework
Virtual Onsite Stages
reportedCandidates describe the final stages as run virtually and as comprehensive, but the reports do not give their order or format. Prepare to switch between coding, design and behavioral modes in one sitting. The expensive mistake is carrying one mode into the next: over-engineering a coding problem you needed to finish, or drawing boxes before anyone has agreed what the system must do. Before each conversation, say out loud which kind it is, and open with that mode's first habit.
What to demonstrate
- Whether a coding answer ends with something that runs and has been traced against a degenerate input
- Whether a design answer starts by agreeing on scale, read-to-write mix and acceptable staleness
- Whether a behavioral answer names a person, a disagreement and what you did about it
- Whether the opening habits (restating the problem, asking for constraints, stating the plan) still appear late in the day
How to prepare
- Book three mocks of different types back to back and ask each interviewer which mode you answered in by mistake
- Write a three-line opening per type. Coding: restate, name the approach and its cost, then type. Design: ask for scale, the read-write mix and what must not break. Behavioral: name the person, the stakes and the decision
- Test your camera, audio and a shared drawing tool before the day, so setup does not cut into the first conversation
2 candidate reports. Individual accounts describe a particular role and hiring cycle.
Okta Software Engineer interview: smooth recruiter screen and abrupt rejection
The recruiter screening felt as though it was going fairly well, but I received an automated rejection shortly afterward with almost no detail. The questions I remember were basic: tell me about yourself, why I wanted to work there, and why I was considering other roles. The process ended so quickly that I did not feel there had been much evaluation beyond that first conversation. Since the scree…
Read full experienceOkta Senior Software Engineer Interview Experience — Four Weekly Rounds, Then Radio Silence
View report detailsPracHub editorial advice for the preparation topics above.
Running plain BFS on a weighted map and calling the result the shortest path
BFS finds the path with the fewest edges, which is the shortest path only when every edge costs the same. Ask about the weights first. With non-negative weights, use Dijkstra with a min-heap in O((V + E) log V), and skip stale heap entries whose distance is larger than the best one recorded. With weights of only 0 and 1, a deque-based 0-1 BFS is linear. With negative weights, neither works, and you should say so. Trace one small graph where the fewest-edge path is not the cheapest before you write the loop.
Flattening the JSON input and averaging before asking what counts as a value and a weight
Pin the contract before coding. What is the path separator, and what happens when a key already contains it? Are array elements indexed into the path? Are non-numeric leaves skipped or errors? What is returned when the total weight is zero? The weighted average is sum(w * v) / sum(w). Guard the zero denominator explicitly instead of letting it raise. For deeply nested input, flatten with an explicit stack so recursion depth is not a hidden limit, and test an empty object, a single leaf and a key collision.
Designing the company-wide IP banlist as one database table that every request queries
The read path runs on every request in every system, while writes are rare, so reads must be served locally from memory. Put a prefix trie in memory if bans cover CIDR ranges or IPv6. Then design propagation: a versioned list that nodes pull, or pushed updates that carry version numbers so a node can detect a gap and resync. State the staleness window you accept between a ban and its enforcement everywhere, what a node does when it cannot reach the source (keep enforcing the last known list), and how bans expire or are lifted.
Answering the rate-limiting design with a token bucket held in each server's memory
Per-node counters behind a load balancer let a client get roughly N times its limit across N nodes. Name the options and their costs. A shared store with an atomic check-and-increment is exact but adds a network hop and a dependency. Splitting the limit across nodes is cheap but imprecise when traffic is uneven. Sticky routing by client key breaks when nodes change. Decide explicitly whether the limiter fails open or fails closed when its store is unreachable, return 429 with Retry-After so clients back off, and say how you keep one noisy client from exhausting shared capacity.
Claiming identity and access management experience you cannot defend under a follow-up
A reported behavioral prompt asks about user lifecycle management or IAM, and one follow-up exposes a claim that was stretched. If your experience is adjacent, say so and describe what you actually built, such as session handling, role checks or offboarding a user's access. Then show you know the basics: provisioning and deprovisioning across systems, OAuth 2.0 as delegated authorization, OpenID Connect as the identity layer on top of it, and SAML assertions for single sign-on. Honest adjacency with correct fundamentals holds up. Inflated ownership does not.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Design a system to manage memory allocation (alloc x and erase ID).
Design a system to manage memory allocation (alloc x and erase ID).
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
- Walk one small example through your approach before writing the whole thing.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement a breadth-first search (BFS) over a weighted map.
Implement a breadth-first search (BFS) over a weighted map.
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about 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?
Given a complex JSON input, parse it, flatten it, and calculate a weig…
Given a complex JSON input, parse it, flatten it, and calculate a weighted average.
Approach
- State the target complexity and say which constraint rules the naive version out.
- Restate the input: its shape, its size, and what is guaranteed about it.
- Choose the data structure from the access pattern, not from familiarity.
Follow-up
- Which test case would catch an off-by-one here?
- What is the worst case, and how likely is it on real data?
Solve a problem involving finding the index that breaks an alternating…
Solve a problem involving finding the index that breaks an alternating parity pattern.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
- State the target complexity and say which constraint rules the naive version out.
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
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
- Parse in one scan: split on
,, then on the first=only, since a value may itself contain=under a future scheme. Accepttexactly once and treat a secondtas a reject rather than last-wins. Push everyv1onto a short list and ignore any other key, so av2can be introduced later without breaking this verifier. - 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. - 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.
- 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 testacc == 0at 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. - Apply the tolerance as a two-sided bound, rejecting when
|now - t| > 300seconds. A sender whose clock runs ahead of yours is an ordinary case, and an unbounded future timestamp is a free replay window. - 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
- Write the grammar on one line before coding:
header := field (',' field)*,field := key '=' value, split on the first=only. - Implement the parser to return
{t: int, v1: [hex, ...]}, rejecting a missingt, a duplicatet, anyv1that is not 64 hex characters, and a header over 1 KiB, all before any cryptography runs. - Implement the verifier: for each active secret compute
HMAC-SHA256(secret, f'{t}.'.encode() + raw_body), compare it in constant time against each parsedv1, and OR the results with no early exit. - Test with a valid signature; the same body with
tmoved 400 seconds into the past; the same body witht400 seconds into the future; a header carrying an unknownv2=alongside a validv1; and a body re-serialised with different JSON key order.
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?
Migrate a live partitioned event table without blocking ingest
usage_event is range-partitioned daily on ingested_at, holds roughly 250M rows per day across 400 live partitions, and is written at 10-40k rows/second. Two changes are required: quantity must move from double precision to numeric(20,6), and a new environment column must become NOT NULL with a default of 'production'. Ingest cannot stop. Give the ordered plan, naming for each step the lock it takes, what that lock blocks, and roughly how long it is held. Identify the one step that cannot be rolled back cleanly once traffic depends on it.
Approach
- Classify the two changes before planning anything. Adding a column with a non-volatile default has been metadata-only since PostgreSQL 11, so it is cheap. Changing double precision to numeric is not binary-coercible, so
alter column ... typerewrites every partition under ACCESS EXCLUSIVE and rebuilds its indexes; on this volume that is hours of blocked ingest and is simply not an option, which is why the plan is expand-and-contract rather than one statement. - Expand: add
quantity_numeric numeric(20,6)andenvironmentwith its default on the parent. Both are catalogue-only but both take a brief ACCESS EXCLUSIVE that cascades to partitions, so run each withlock_timeoutset to a second or two and retry on failure. A queued ACCESS EXCLUSIVE request blocks every reader behind it, which is how a metadata-only change turns into an outage. - Dual-write: deploy producer code that populates both columns on every insert, and leave it running before anything reads the new column. This is the step that cannot be reverted cleanly. Once readers depend on quantity_numeric, reverting the writer leaves rows with a null there, and the gap is only discoverable by re-reading the old column, which the readers have stopped doing.
- Backfill older partitions in batches keyed on the primary key, oldest first, committing every few thousand rows with a pause between batches, and skipping the partition still receiving writes until it rotates. Each batch is an ordinary UPDATE taking row locks only. The cost is bloat and WAL rather than blocking, so watch dead tuples and let autovacuum keep pace instead of wrapping 400 partitions in one transaction.
- Make NOT NULL cheap with the three-step form:
add constraint ... check (environment is not null) not valid(brief ACCESS EXCLUSIVE, no scan), thenvalidate constraint(SHARE UPDATE EXCLUSIVE, scans while reads and writes continue), thenset not null, which from PostgreSQL 12 uses the validated check and skips its own full scan. Do this per partition, then on the parent. - Switch and contract: move reads to the new column behind a flag, verify over a full period that both columns agree on freshly written rows, drop the old column (metadata-only), and only then remove the dual-write. Any index on the new column goes on with CREATE INDEX CONCURRENTLY per partition, since CIC is not supported on a partitioned parent: create the parent index with ONLY, build each child concurrently, then ALTER INDEX ... ATTACH PARTITION until the parent index becomes valid.
Follow-up
- A CREATE INDEX CONCURRENTLY fails halfway through the partition list. What state is the table in, how do you detect it, and what do you run?
- The producer computes quantity itself. What happens to a request already in flight when the dual-write deploy lands, and does it matter?
- Give two queries that prove the backfill is complete: one cheap enough to run every minute, one authoritative.
Explain why the metering dashboard scans every daily partition
usage_event is range-partitioned daily on ingested_at and holds tenant_id, workspace_id, environment, sku, quantity numeric(20,6), occurred_at and ingested_at. The only relevant index is on (occurred_at). A dashboard runs select sku, sum(quantity) from usage_event where tenant_id = $1 and date_trunc('hour', occurred_at) >= $2 and environment = 'production' group by sku, and EXPLAIN shows a sequential scan of every partition. Give each distinct reason, rewrite the predicate so an index can serve it, propose the index, and state the write cost its column order adds.
Approach
- Separate the three causes rather than blaming one. First,
date_trunc('hour', occurred_at)wraps the column, so the predicate is not sargable against a btree on the bare column. Second, pruning keys off ingested_at while the query constrains occurred_at, so no partition can be excluded. Third, even made sargable, (occurred_at) is not tenant-leading, so for one tenant among thousands the scan reads the whole time range and discards nearly all of it. - Rewrite the bound carefully, because the obvious rewrite is only conditionally equivalent.
date_trunc('hour', x) >= $2equalsx >= $2only when $2 is already hour-aligned; for an arbitrary $2 it meansx >= date_trunc('hour', $2) + interval '1 hour'. Normalise the parameter in the caller and leave the column bare. - Restore pruning with a second, redundant predicate on the partition key:
ingested_at >= $2 - interval '<late-data horizon>'. State both sides of it. It prunes to a handful of partitions, and it silently omits any event whose ingest lagged past that horizon, which is precisely what a producer replay produces. Either document the horizon as a stated bound, or partition on occurred_at and move the problem into the dedup window instead. - Propose
(tenant_id, occurred_at) include (sku, quantity)per partition. A partial indexwhere environment = 'production'mostly saves size rather than selectivity, since production dominates the three environments; take it if non-production is a meaningful share and skip it otherwise. - Price the write path honestly. At roughly 250M rows/day each extra index is another insert plus WAL per row, and a tenant-leading key scatters inserts across one hot leaf per active tenant instead of appending to a single rightmost leaf, so page dirtying and random I/O both rise. An INCLUDE payload widens every leaf entry and enlarges the index accordingly.
- Add the index-only-scan caveat before someone reports it as a regression: on a freshly appended table the visibility map is not yet set for recent pages, so the INCLUDE columns still cost heap fetches until autovacuum has been through, and the newest hour is exactly the data the dashboard reads.
Worked solution 30 min
- Build 30 daily partitions with skewed tenants, one holding about 40% of the rows, then ANALYZE.
- Run
explain (analyze, buffers)on the original query and record how many partitions were scanned and the rows removed by filter. - Apply the rewritten predicate and the index, re-run, and confirm the plan lists only the partitions inside the ingested_at bound.
- Re-run with $2 set to a non-hour-aligned timestamp and confirm the rewritten and original predicates return identical rows.
- Insert an event with ingested_at six hours past occurred_at and check whether the pruning predicate excludes it.
Follow-up
- CREATE INDEX CONCURRENTLY is not supported on a partitioned parent. Give the sequence that gets this index onto 400 existing partitions without blocking ingest.
- One tenant holds 200 times the median row count and the dashboard still times out for them with the index in place. What changes?
- Should this read hit
usage_rollup_hourlyinstead? State what that costs in freshness and what the watermark lets you promise.
Explain how you would architect a system to handle high concurrency an…
Explain how you would architect a system to handle high concurrency and rate limiting.
Approach
- Choose a partition key and say what query it makes expensive.
- Name the failure you are designing for, then the recovery path.
- Name the read and write paths separately; they rarely have the same bottleneck.
Follow-up
- What would you drop to keep the system up under load?
- How does this behave when that dependency is down for an hour?
Design an IP banlist that maintains a list of banned IPs across all sy…
Design an IP banlist that maintains a list of banned IPs across all systems in the company.
Approach
- State the consistency you need, and where you are willing to be stale.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Fix the scope first: who calls this, how often, and what they do when it fails.
Follow-up
- What breaks first when traffic grows ten times?
- What would you drop to keep the system up under load?
Design a machine-readable error contract for the gateway
The edge gateway serves roughly 30k requests/second to SDKs and CI pipelines that retry automatically. Today every failure returns 500 with a prose message that clients string-match on. Design the error contract: the response body fields, and the status code for a malformed body, a revoked credential, a scope the credential lacks, a row belonging to another tenant, a reused idempotency key sent with a different body, an exceeded rate limit, and an unreachable dependency. For each, state whether the client may retry and on what schedule. Deliverable: the envelope schema plus the status-to-retry table.
Approach
- Split the envelope by audience: a stable
codestring for programs, amessagedocumented as human-only and free to change, arequest_idthat joins to gateway logs, and adetailsarray for per-field problems. The code list is an enum that only ever grows. - Assign status by who has to change something: 400/422 for the caller's bytes, 401 for a credential that no longer authenticates, 403 for a scope or entitlement, 404 rather than 403 for a row in another tenant because 403 confirms the identifier exists, 409 for an idempotency conflict, 429 for a limit, 503 for a dependency.
- Derive retryability from the method and the idempotency key rather than from the status: a 5xx or a timeout is an unknown outcome, not a failure, so GET/PUT/DELETE may be retried under HTTP semantics and POST only when it carries an idempotency key.
- Put the schedule in the response: Retry-After on 429 and 503 overrides the client's own backoff; otherwise capped exponential backoff with full jitter, sleeping uniformly in [0, min(cap, base * 2^attempt)], bounded by a total attempt budget so retries expire before the caller's deadline.
- Write the negative rules into the published contract: clients must never parse
message, must tolerate unknowncodevalues by falling back to the status class, and a code's meaning is never redefined once shipped.
Worked solution 20 min
- Write the envelope as a JSON schema with four top-level fields and say which are guaranteed present on every error.
- Fill a seven-row table: condition, status, code string, retryable yes/no, and the schedule or the reason retrying cannot help.
- For each non-retryable row, write the one thing the caller must change (bytes, credential, plan, key) so nothing is marked non-retryable without a remedy.
- Add the unknown-outcome row for timeouts and 5xx separately from the other rows, and give it an action other than 'treat as failed'.
- Write two sentences of client guidance: honour Retry-After when present, apply full jitter otherwise, and stop at the attempt budget.
Follow-up
- A customer reports they retried a 500 from POST /v1/runs and ended up with two sandboxes billed. Whose bug is it, and what in your contract permits their reading?
- You need to add a new error code next quarter without a version bump. What did the v1 contract have to say for that to be non-breaking?
Metering partition crash-loops and the sealing watermark freezes
One metering-ingest partition has stopped advancing. Lag grows linearly, the consumer restarts about every 40 seconds, and the same offset appears in every startup log while other partitions stay healthy. Events are committed in batches of a few thousand and the acknowledgement follows the commit. Sealing is six hours away and source_max_ingested_at for that partition's tenants is frozen. Give an ordered checklist, a containment action available within minutes, and the durable fix, saying what each does to exactly-once accounting.
Approach
- Distinguish a poison record from a capacity problem in one measurement: compare the offset and the exception across restarts. An identical pair every time is deterministic failure on one record, whereas a throughput problem still advances the offset between crashes.
- Read the record from a separate consumer group so the bytes can be inspected without perturbing the stuck consumer, then classify the defect: schema violation, a quantity failing the non-negative check, a null workspace, an unmappable SKU enum, or a payload past a size limit. That classification decides whether this is a producer bug or a missing consumer guard.
- Account for batch granularity before acting. With commits of a few thousand, one bad record fails thousands of good ones, so the blast radius is the batch. Halve the batch around the offset to isolate the record, or move to per-record error isolation so the radius becomes the record.
- Contain by diverting that record to a dead-letter store with its raw bytes and offset, then resume. This is safe here precisely because the acknowledgement follows the commit: the good records from the failed batch are re-consumed and absorbed by the uniqueness check on (tenant_id, idempotency_key) rather than counted twice.
- Make the fix durable with per-record error isolation, a bounded poison counter, and an alert on dead-letter rate rather than on lag alone, since lag only reveals this after the sealing margin has already been eaten.
- Check the horizon before replaying anything. The unique index lives on a daily-partitioned table and therefore includes the partition key, so it deduplicates within a day only; a replay landing on a later ingest day needs the separate dedup store or it double-counts into a tenant's bill.
Follow-up
- Move the acknowledgement before the commit and describe exactly what is lost and what is duplicated in each of the two crash windows.
- Sealing is in six hours and the partition will not drain in time. What do you seal on, and what does the invoice have to record so the difference is explainable later?
- A producer replays two weeks of events next month. Which part of your fix stops holding, and what is the dedup horizon you would actually configure?
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.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the loop and prepare the recruiter screen
- Mark every line of the posting as done, adjacent or new, and write the one-sentence version of each adjacent line
- Choose three projects for the deep-dive interviews and write one page on each: constraint, rejected option, measurement before and after, and what went wrong
- Write the recruiter questions: what the team builds, which language it works in, and which assessment platform and editor you will use
- Refresh identity basics in your own words: provisioning versus deprovisioning, OAuth 2.0 versus OpenID Connect, and what a SAML assertion carries
Deliverable: A marked-up posting, three project pages, and a one-page identity-concepts note written without references.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Graph search and simulation coding
- Implement the reported BFS over a weighted map both ways: plain BFS on unit weights, then Dijkstra with a min-heap, and find a graph where the two answers differ
- Practise multi-source BFS on the Rotten Oranges bank question and single-source BFS on the word-transformation question from the Medium to Hard LeetCode Set
- Build the reported alloc x / erase ID allocator. First state the contract you assume (for example leftmost fit, -1 when no block fits, erase returning the count of freed units), then test a fragmented memory where no block fits
- Run every solution against an empty or minimal input before calling it done
Deliverable: Four graph solutions and one allocator with its assumed contract written at the top, each with its complexity stated and a degenerate-input test.
Practice prompt ↗Practice prompt ↗03Array scans and parsing under a timer
- Solve the reported alternating-parity break with a single scan, and include negative numbers in your tests
- Solve the reported peaks problem: if the constraint is a minimum index distance d, insert h[j - d] into an ordered set as j advances and query the nearest value to h[j], for O(n log n)
- Solve the reported JSON flatten and weighted average with an explicit stack, handling zero total weight and key collisions
- Do Validate IPv4 Address List from the bank. Before coding, state the validation rules you assume and would confirm with the interviewer, for example whether leading zeros, out-of-range octets or the wrong number of parts make an entry invalid
- If your assessment runs on a proctored third-party platform, solve at least one of these in that editor with a timer you do not extend
Deliverable: Four timed solutions with a written list of the edge cases and assumed rules each one handles.
Practice prompt ↗Practice prompt ↗04Authorization logic and the coding and SQL worked exercises
- Solve Evaluate Role-Based Access with Deny Precedence from the bank. Before coding, state the rules you assume and would confirm with the interviewer, such as an explicit deny overriding any allow and no matching rule meaning deny
- Work the webhook signature exercise (drill-coding-3) and run its checks, including the timestamp tolerance in both directions
- Work the partition-pruning SQL exercise (drill-sql-2) and explain the three separate causes of the full scan out loud
- Write the security implications of one API you have built: authentication, authorization per resource, input validation and what an error response reveals
Deliverable: An access-evaluation function with its assumed rules written down and tests for deny precedence, plus completed checks for both worked exercises.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Rate limiting and the IP banlist
- Design the reported high-concurrency and rate-limiting system: algorithm choice, where the counter state lives, what happens if the store fails, and the 429 response with Retry-After
- Design the reported company-wide IP banlist: in-memory reads, versioned propagation, a stated staleness window, CIDR support and expiry
- Work the gateway error-contract exercise (drill-design-4), paying attention to the 429 and 503 rows and to retries
- Sketch Scale an Authorization Checker from the bank: what gets cached, how a revoked permission propagates, and how stale a decision may be
Deliverable: Two design write-ups, each opening with requirements and numbers and closing with failure modes, plus the completed error-contract table.
Practice prompt ↗Practice prompt ↗06Data flow, queues and schema
- Write the reported end-to-end data flow for one feature you know: the database choice and its access pattern, where a message queue sits, and the delivery guarantee it gives
- Review message-queue fundamentals from the bank topics: at-least-once versus at-most-once delivery, ordering per key, consumer scaling and replay
- Sketch Design a Metrics Storage Platform from the bank: write path, retention, rollups and the query it must answer quickly
- Work the poison-message debugging drill (drill-debugging-5) and write the containment step and the durable fix separately
Deliverable: One data-flow diagram with schema and queue semantics written beside it, and a debugging checklist for a stuck consumer.
Practice prompt ↗Practice prompt ↗07Deep-dive and behavioral rehearsal
- Answer each reported behavioral prompt with a chosen project: a difficult trade-off, mentoring or prototype to production, a disagreement, and identity or lifecycle management experience
- Rehearse the review-disagreement drill (drill-behavioral-6), demonstrating the race rather than asserting it
- Have someone ask why three times on your weakest project story and rework the point where you run out of answers
- Run one mixed mock (coding, then design, then behavioral) and note where you carried one mode into the next
Deliverable: A one-page map from each reported prompt to a project, plus mock notes naming the mode switches you missed.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Candidates report four behavioral themes for this role: justifying a difficult technical trade-off, mentoring a peer or taking a project from prototype to production, disagreeing with a teammate's technical approach, and experience with user lifecycle or identity and access management. Prepare fewer stories and know them more deeply. For each one, be ready to say what you chose, what you rejected, what it cost, and what evidence would have changed your mind. For the identity prompt, describe your real experience accurately and show the fundamentals, rather than stretching an adjacent project.
Describe a time you had to make a difficult technical trade-off. How d…
Describe a time you had to make a difficult technical trade-off. How did you justify it?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
Follow-up
- How did you know your change caused the improvement?
- What would you do differently if you ran that again?
How do you handle situations where you disagree with a teammate’s tech…
How do you handle situations where you disagree with a teammate’s technical approach?
Approach
- Close with what you would do differently, concretely.
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Resolve a review disagreement over a quota check
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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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?
- 01
Describe a time you had to make a difficult technical trade-off. How did you justify it?
- 02
Tell me about a time you had to mentor a peer or lead a project from prototype to production.
- 03
How do you handle situations where you disagree with a teammate's technical approach?
- 04
Discuss your experience with user lifecycle management or identity and access management.
- 05
A reviewer says a select-then-insert quota check is safe because it runs at repeatable read. How do you take that disagreement to a resolution?
Is this an official Okta interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Okta. Rounds and questions reflect what candidates have reported, not a process Okta has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How long should I expect the entire process to take?
Candidates report five stages over roughly four to six weeks, and other reports put it at three to six weeks depending on the team and your location. Plan your preparation so coding and design are both ready before the virtual onsite stages. Ask your recruiter for the expected timeline at the first call.
PracHub interview research ↗Are the coding assessments proctored?
Some assessments are reported to run on third-party platforms that are timed and proctored. Ask which platform yours uses and solve at least one practice problem in its editor beforehand, so the tooling is not what slows you down.
PracHub interview research ↗How should I approach the technical questions?
Explain why you made each decision, not just what the solution is. Say why you chose a data structure or pattern over the alternatives, and bring up trade-offs such as memory against speed without waiting to be asked. When a problem is underspecified, state the constraints you are assuming before you write code, then check them against a small example.
PracHub interview research ↗How much should I prepare on SAML or OAuth?
One reported behavioral prompt asks about user lifecycle management or identity and access management, so refresh the fundamentals before the loop. Be able to explain provisioning and deprovisioning, OAuth 2.0 versus OpenID Connect, and what SAML single sign-on exchanges. If your own experience is adjacent rather than direct, say so and describe what you actually built.
PracHub interview research ↗Which programming language should I use?
Use the language you can write fastest and most correctly without references. Ask your recruiter which languages the assessment platform supports and which language the team works in, and if they differ, practise in the one you will actually be tested in.
PracHub Software Engineer practice ↗What kinds of questions are reported for this role?
Coding questions cover graph search, array scans, a memory allocator simulation and JSON parsing with a weighted average. Design questions cover an IP banlist shared across systems, high concurrency and rate limiting, schema for a scalable service, and end-to-end data flow through databases and message queues. Behavioral questions cover trade-offs, mentoring, disagreement and identity experience. The reports do not tie specific questions to specific rounds.
PracHub Software Engineer practice ↗What if I do not hear back after a stage?
Some candidates report inconsistent communication during the process. If the expected timeframe passes without word, send your recruiter a short, polite follow-up that names the stage you completed and asks about next steps.
PracHub Software Engineer practice ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-24 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-24 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-24