As a Software Engineer at Omni Federal, you are at the forefront of modernizing critical systems and delivering high-impact technical solutions. Omni Federal specializes in driving digital transformation, often working within complex environments that require a blend of rapid development, security-conscious engineering, and cloud-native architecture.
This role is not just about writing code; it is about solving systemic challenges that directly influence the mission success of the organization's partners. You will be expected to contribute to projects that demand both technical rigor and a pragmatic approach to problem-solving. Whether you are working on DevSecOps pipelines, cloud infrastructure, or custom software development, your work will be central to the company’s objective of delivering high-quality, reliable, and secure software at scale.
Candidates who thrive here are those who possess a "get things done" mindset and an ability to navigate ambiguity. Because Omni Federal operates in specialized sectors, you will find yourself collaborating with cross-functional teams of engineers, program managers, and leadership to deliver solutions that are not only functional but strategically aligned with long-term goals.
Recruiter Screen
reportedThe person on this call usually cannot evaluate your code and does not need to. They write a short paragraph, and that paragraph is what a hiring manager skims when deciding who to put on your loop. So the test is not whether your work was hard, it is whether a non-engineer can repeat it correctly. Name systems by what they did rather than by their internal codename, give each project a shape (what was breaking, what you changed, what happened after), and keep the whole walkthrough near ninety seconds. Depth that cannot survive a paraphrase reads as vagueness.
What to demonstrate
- Whether a non-engineer can restate your projects without distorting them, since their paraphrase is what travels to the hiring manager, not your sentences
- Whether each project has a shape rather than a stack list: the failure or constraint, the change you made, the result and how it was measured
- Whether you can say what was yours inside a team project without either inflating it or disappearing into the plural
How to prepare
- Rewrite each headline project as two sentences with no internal system names and no acronyms outside your company, then say them to someone outside engineering and have them repeat them back. Fix whatever came back wrong
- Attach one measured number to each project: the baseline, the change, and the window it was measured over. Where nothing was ever measured, say that plainly rather than reaching for a plausible percentage
- Time the background walkthrough against a clock. If it runs past two minutes, compress the earliest role to a single clause and spend the recovered time on the most recent one
Technical Assessments
reportedThe same problem is scored by two different mechanisms depending on the format, and preparing for one does not cover the other. With a person watching, partial progress is visible and a hint is a correction you can absorb; silence is the expensive failure, because nobody can read a half-written function. With an automated grader there is no partial credit for what you were about to do, nobody to ask, and the worked examples in the prompt are the entire specification. Read them as a contract, down to whether an empty result should be an empty list or no output at all.
What to demonstrate
- In a live session, whether your commentary tracks what your hands are doing, and whether a hint redirects you or gets defended against
- In an automated one, whether you cover the cases the examples do not show, since the hidden cases are where the score moves
- Whether you manage the clock on purpose: abandoning an approach that is not converging while there is still time to write something simpler that finishes
How to prepare
- Have someone hand you a problem and feed you one deliberately wrong hint. Practise testing it against a concrete case instead of accepting or rejecting it on authority.
- Do one timed run a week in a plain browser editor with autocomplete, linting and your own snippets switched off, which is closer to what these environments give you
- For the automated format, write the harness before the solution: a main that feeds the worked examples plus an empty and a single-element case and prints expected against actual, so a wrong submission is caught by you first
Leadership Engagement
reportedBecause the format is not fixed, the first job in the room is classification. Listen to the opening question and decide what it is: a probe into work you have already described, a fresh problem to solve now, or a conversation about how you operate. Each wants a different register, and the common failure is forcing a rehearsed structure onto a question that did not ask for it. Running a full design ritual on a ten-minute debugging question reads as not listening. When you cannot tell which it is, ask how long they want to spend and answer at that depth.
What to demonstrate
- Whether the shape of your answer matches the question, so a yes-or-no gets answered before it is justified and an open prompt gets a direction before a detour
- Whether you check how much depth is wanted instead of deciding for them, and whether you stop when the answer is complete rather than continuing until someone interrupts
- Whether you can be redirected in the middle of an answer without restarting it from the beginning
- Whether a question outside your experience gets an honest boundary followed by reasoning from what you do know, instead of a confident answer with nothing behind it
How to prepare
- Rehearse one project at three lengths, roughly thirty seconds, three minutes, and a full walkthrough at the depth of a design review, and practise switching between them when someone interrupts mid-telling
- Have someone ask you five questions of deliberately mixed type in one sitting without telling you the types, and score only whether you identified each one correctly before you started answering
- Draft the sentence you will use to check depth, along the lines of asking whether the short version is useful here or they want the detail, and use it in a real conversation this week so the day of the round is not its first outing
PracHub editorial advice for the preparation topics above.
Leaving accessibility conformance to a review at the end of the project
The obligation is usually statutory and expressed against WCAG success criteria at AA, and those criteria cut straight through component architecture rather than sitting on top of it. Custom select menus, modals and date pickers have to manage focus and expose correct roles and names; 2.4.11 Focus Not Obscured (AA) constrains sticky headers and cookie bars; 2.5.8 Target Size (Minimum) (AA) requires a 24 by 24 CSS pixel target unless a listed exception applies; 3.3.8 Accessible Authentication (Minimum) (AA) rules out a login step that depends on a cognitive function test with no alternative; and 2.2.1 Timing Adjustable (Level A) collides directly with the short session timeout a security review asked for, since the user must be able to extend it. Retrofitting these means rewriting the component layer and the session design, so they belong in the component contract and in the definition of done from the first sprint.
Using soft delete (deleted_at IS NOT NULL) as the answer to a records-retention requirement
It fails both directions at once. The obligation to destroy is unmet because the bytes remain in the primary table, the backups, the search index, the analytics extract and any vendor queue that received a copy, and a competent disclosure request or audit will find them. Meanwhile the record is invisible to staff who legitimately need it, so the organisation loses the ability to answer questions it is still required to answer. Retention needs a destruction pipeline that enumerates derived copies, checks legal hold at execution time under lock, emits a receipt, and fails closed when a copy is unreachable - and the tombstone row that proves destruction happened has to survive the destruction.
Quoting amortised or average cost as if it were a worst-case guarantee
Appending to a dynamic array is amortised O(1), but the append that triggers a resize copies every element, and hash lookup is constant only while the hash spreads the actual keys. Say which guarantee you are offering when the caller cares about the latency of one call rather than the total over many.
Reading the constraints as preamble rather than as part of the problem
The bounds are usually there to eliminate the obvious approach: n up to 10^5 makes an O(n^2) scan roughly 10^10 operations, far outside any per-test time budget, and an input larger than memory rules out loading it at all. When a bound is not given, ask for it, then say out loud which approach it kills.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Replay sixty million determinations after a retroactive rule correction
A regulator corrects three clauses of a ruleset with effect six years back. Sixty million determination rows fall under the affected rule family, each carrying rule_version_id, evidence_snapshot_hash and a trace of the clauses that fired. Evaluation is a pure function costing about 8 ms of CPU, but each replay must rehydrate the frozen evidence snapshot from a content-addressed store capped at 500 fetches per second shared with live traffic. Replaying everything is correct. Explain why it is not viable, and give the algorithm that is.
Approach
- Cost the naive run before optimising it. CPU is not the constraint: 60 million evaluations at 8 ms is about 133 CPU-hours and parallelises freely. The store is: 60 million fetches against a 500 per second ceiling is 120,000 seconds, roughly 33 hours of wall clock while consuming the entire budget live traffic also needs. The run is correct because replay is deterministic and unaffected determinations converge on the existing row through the partial unique index, so it is purely a cost problem.
- Build an inverted index from clause to determination. Either a separate determination_clause table indexed on clause_id, or a GIN index over the trace array. The three corrected clauses then yield a candidate set by index scan instead of a full scan, typically well under one percent of the 60 million rows.
- Recognise that the fired-clause filter alone is unsound. A correction that widens a guard makes a clause newly reachable, so determinations that never reached it before can change now, and those are precisely the denials the correction was issued to reverse. If the trace only records clauses that fired, the filter silently omits the population the regulator cares about.
- Close the gap with what the trace can actually support, and be explicit that the target is a sound superset, not an exact set. If the trace records evaluated-and-false clauses as well as fired ones, include both: every determination that can change is then selected, along with some that cannot — a determination that already passed the widened guard is selected and replays identical, because widening a guard cannot exclude an input it already admitted. That asymmetry is the correct trade. A false positive costs one rehydration; a false negative is an uncorrected determination. If the trace records only fired clauses, fall back to a wider superset: every determination under the affected rule_versions whose effective period intersects the corrected period, which is far larger than the clause filter and still orders of magnitude under 60 million.
- Deduplicate the rehydration, not the evaluation. Distinct evidence_snapshot_hash values are the unit of store work, and a single snapshot attached to several cases in a household or an appeal chain is fetched once and evaluated per determination. Order the candidate scan by hash so the cache hits are adjacent rather than scattered across the run.
- Make the run resumable and rate-limited by construction: a durable cursor over the candidate set, a token bucket sized to the share of the 500 per second ceiling you are permitted, and writes that rely on the uniqueness key rather than a read-then-insert, so a restart after a crash converges instead of producing a second current determination.
Worked solution 40 min
- Write out the naive budget explicitly: 60,000,000 divided by 500 fetches per second, converted to hours, next to the 133 CPU-hours, and state which number is the constraint.
- Construct a ruleset with a guard clause G and a downstream clause C, where G is a pure reachability guard — it admits or blocks, and changing it changes nothing C reads. Build 1,000 determinations: 60 passed G and fired C, 90 evaluated G and failed it so C was never reached, and 850 took an earlier branch and never evaluated G at all.
- Apply a correction that widens G so all 90 previously-failing determinations now pass it and reach C. Establish ground truth first by replaying all 1,000 and recording which results differ; then run the fired-clause filter and count how many of that changed set it selects.
- Re-run with the filter extended to evaluated-and-false clauses, and compare its candidate set against the control's changed set in both directions separately.
Follow-up
- The correction changes an amount rather than an outcome. Does your candidate filter change, and does the notice obligation?
- A replayed determination comes back identical. Do you write anything at all, and what does an auditor need to see that you checked it?
- Halfway through the run the regulator issues a correction to the correction. What happens to the work already done?
Find every determination a corrected reference table can change
A reference table (a rate schedule, threshold list or jurisdiction list) is corrected: version v is superseded by v' governing [p1, p2]. You have a graph of about 1,800 rule_version nodes, 40,000 clause nodes and 5,000 reference-table-version nodes, with roughly 90,000 reads edges from clause to table version; each rule_version has a governing date range. Determinations number 60 million, each carrying rule_version_id and effective_from. Return the determination set that could change. Name the traversal, its complexity, and what you do if the graph contains a cycle.
Approach
- Traverse backwards from the corrected table version, not forwards from every rule. Reverse the reads edges once into an adjacency list keyed by table version, then breadth-first from v' to collect the clauses that read it and the rule_versions that own those clauses. One BFS is O(V + E), about 135k nodes and edges; the forward alternative asks reachability per rule_version and is O(V times E).
- Filter each edge by period intersection as you traverse. A rule_version only reads the corrected text if its governing range intersects [p1, p2]; an edge to a rule whose period ended before p1 is a historical fact, not a dependency, and following it inflates the replay set with determinations that provably cannot move.
- Intersect at the determination level with a second predicate, not by scanning 60 million rows: the affected rule_version_id set drives an index range scan on (rule_version_id, effective_from), and effective_from must fall inside [p1, p2]. The graph part is milliseconds; the determination part is what the index has to be built for.
- Detect cycles rather than assuming a DAG. A reference table derived from aggregate determination output and read back by a rule is a real configuration, and it is a defect, but a naive BFS with a visited set will terminate quietly and give an answer that hides it. Mark the cycle, report it, and cap the traversal depth so a malformed edge cannot stall the job.
- Report the set with its provenance: which clause chain connects each rule_version to the corrected table. A blast radius nobody can explain is a number an auditor will not accept, and the same chain is what lets a reviewer overrule an over-broad inclusion.
Follow-up
- The corrected table is read by a clause that is itself behind a feature guard never enabled in that period. Do you keep those rule_versions in the set?
- Two reference tables are corrected in the same maintenance window. Is the combined blast radius the union of the two, and when is it larger?
- The reads edges are inferred from a static scan of clause source rather than declared. What does that do to the soundness of your answer?
Parse a fixed-width record with packed-decimal amount fields
A nightly file from a system of record arrives as fixed-length 180-byte records in EBCDIC code page 037. Per the copybook, bytes 1-40 are a character name field, bytes 41-48 a character date, bytes 49-52 an amount declared PIC S9(5)V99 COMP-3, and the rest character. The trailer record carries a record count and the sum of every amount field. Write the parser and state, in minor currency units, what a whole-record EBCDIC-to-ASCII text conversion does to a packed amount before it ever reaches your validation.
Approach
- Parse by field against the copybook offsets, never by transcoding the record. Slice bytes 1-40 and 41-48 and decode those with cp037; slice bytes 49-52 and hand them to a packed-decimal unpacker that never sees a codec.
- Unpack COMP-3 explicitly: two BCD digits per byte, and in the final byte the high nibble is the last digit while the low nibble is the sign. Nibble C and F are positive and D is negative under the common convention, so assert the sign nibble rather than defaulting an unrecognised one to positive. S9(5)V99 is seven digits plus a sign nibble, which is eight nibbles, which is exactly the four declared bytes.
- Return the value as an integer count of minor units. V99 is an implied decimal position with nothing stored for it, so the seven unpacked digits already are the minor-unit amount; converting to a float to reinsert a decimal point reintroduces the representation error the packed format exists to avoid.
- Reject the batch on the trailer, not per record. Accumulate the record count and the integer sum of every amount, compare to the trailer, and fail the whole file rather than post a partial batch. A corrupted amount that still parses is invisible to per-record validation and visible only to the control total.
- Complexity is O(total bytes) with O(1) working memory beyond one record buffer and two accumulators; the file is read as a byte stream, so nothing here needs the file resident.
Follow-up
- The copybook gains an OCCURS DEPENDING ON clause, so record length now varies with a count field. How does your offset arithmetic change?
- A record contains a sign nibble of 0xA. Is that valid, and what does your parser do with it?
- The sender starts padding numeric character fields with EBCDIC zeros in a field you decode as text. What breaks and where do you catch it?
Measure time in status from an append-only case event log
case_event(case_event_id, case_id, reopen_cycle, seq BIGINT, event_type TEXT, occurred_at TIMESTAMPTZ, recorded_at TIMESTAMPTZ) is append-only with UNIQUE (case_id, seq). Staff backdate occurred_at; recorded_at is when the row landed. A case can be reopened, so submitted and determined repeat. Write a query returning one row per decision episode with the interval from its submitted to its determined, plus a flag for episodes still open. State which column you order the window by and why the other one gives wrong answers, and say what your query returns for a cycle whose determined carries an occurred_at earlier than its submitted.
Approach
- Partition on the real grain,
(case_id, reopen_cycle). Withcase_idalone, an open cycle'ssubmittedtakes the next cycle'ssubmittedas its LEAD, so a cycle that never closed is reported closed with an interval spanning a cycle boundary. KeepLEAD(event_type)in the output so that is detectable rather than assumed. - Order by
seq, notoccurred_at.seqis unique per case by constraint, so the ordering is total and the result is deterministic.occurred_atis asserted by staff: adeterminedbackdated below its ownsubmittedswaps the two rows, thesubmittedrow becomes last in its partition, LEAD returns NULL, and a cycle that was decided is reported still open — it leaves the completed-cycle statistics entirely rather than showing up as a bad number. - Use LEAD over the filtered event set:
SELECT case_id, reopen_cycle, occurred_at AS submitted_at, LEAD(occurred_at) OVER w AS determined_at, LEAD(event_type) OVER w AS next_type FROM case_event WHERE event_type IN ('submitted','determined') WINDOW w AS (PARTITION BY case_id, reopen_cycle ORDER BY seq), then keep the rows whereevent_type = 'submitted'. WHERE is evaluated before window functions, so filtering to two event types first is both correct and cheap. - Separate pairing from measurement, because
seqonly fixes the first. Ordering byseqguarantees you paired the right two rows; it cannot repair a timestamp a human asserted, so a backdated cycle still yieldsdetermined_at - submitted_atbelow zero. Emit it as computed alongside(determined_at < submitted_at) AS asserted_interval_negative. Do not clamp withGREATEST(..., interval '0')and do not swap the endpoints: the negative value is the only evidence the entry is wrong, and the flag is what keeps it out of the published average without hiding it from the people who can correct it. - Carry the system-time measure beside the asserted one:
recorded_at - LEAD(recorded_at)inverted, i.e.LEAD(recorded_at) OVER w - recorded_at. Precondition for calling it non-negative:recorded_atis assigned by the database at insert and appends for one case are serialised — a per-caseseqissued under the case row lock gives you both properties at once. If a case can be appended to concurrently,recorded_atcan invert againstseqtoo and the flag must cover both measures. - Handle the open episode as data, not as a default: when LEAD returns NULL there is no
determinedyet, so emitdetermined_at IS NULLand astill_openflag. Coalescing tonow()silently converts a censored observation into a completed one and drags every average down. - Be explicit about frames. LAG and LEAD are not frame-sensitive — they address the partition directly — but the moment you add a running aggregate, the default frame is
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, where CURRENT ROW in RANGE mode means the last peer. Ordering on a tie-prone timestamp therefore makes peers of distinct events and sums them all at once; ordering on uniqueseqmakes RANGE and ROWS coincide.
Worked solution 30 min
- Seed one case with five cycles: two clean closed cycles; one open cycle holding only a
submitted; one cycle whosedeterminedhas anoccurred_ateight days before itssubmittedbut arecorded_atfifteen days after it; and one cycle whose two events share anoccurred_atto the millisecond. - Write the LEAD query ordered by
seq, keepingnext_type, and recordasserted_interval, the system-time interval and the negative flag for all five cycles. - Re-run the identical query ordered by
occurred_atand diff the two result sets row by row, noting which cycle changes category rather than value. - Drop
reopen_cyclefrom the PARTITION BY and confirm the open cycle acquires a pair withnext_type = 'submitted'that spans a cycle boundary. - Add a running
COUNT(*)with the default frame ordered byoccurred_at, then byseq, and compare the two columns on the tied pair.
Follow-up
- The published service standard is in business days in the case's jurisdiction. What does this query have to become, and where does the holiday calendar live?
- Two
determinedevents exist in one cycle because a correction was recorded. Which one does your query pair, and which one should it pair? - Rewrite the still-open flag so a cycle with
withdrawnbetweensubmittedanddeterminedis excluded rather than counted as open.
A quarterly payout total that triples through two joins
A quarterly report sums disbursed amounts per program. It joins case to determination (one current row per reopen cycle), determination to disbursement_instruction (one row per benefit period, plus compensating reversal rows carrying reversal_of_instruction_id), and case to case_event to count transitions. Totals come out roughly triple the payment rail's settled figure. Write the corrected query returning program_code, settled_minor and transition_count, and explain the arithmetic that broke. Amounts are integer minor units; do not reach for SUM(DISTINCT ...).
Approach
- Say the grain out loud for every table before writing a line:
caseis one row per case,determinationis one row per (case, reopen_cycle) once filtered tois_current,disbursement_instructionis one row per (determination, benefit period),case_eventis one row per transition. Joining a one-row-per-case anchor to two independent one-to-many children multiplies them: a case with 3 instructions and 12 events yields 36 rows, and every amount is counted twelve times. - Note the second fan-out most candidates miss:
is_currentis unique per (case_id, reopen_cycle), not per case, so a case reopened twice contributes three current determinations and multiplies the event branch again. - Reduce each branch to a common grain in its own CTE before joining. Aggregate instructions up to
case_idthroughdetermination, aggregatecase_eventtocase_id, then LEFT JOIN both ontocase— now each side contributes at most one row per case and the products cannot form. - Net the reversals arithmetically rather than by filtering:
amount_minorcarriesCHECK (amount_minor > 0), so a reversal is a positive row whose sign comes from its role —SUM(CASE WHEN reversal_of_instruction_id IS NULL THEN amount_minor ELSE -amount_minor END). Filtering reversals out instead leaves the original settlement in the total and overstates it. - Reject
SUM(DISTINCT amount_minor)explicitly: two genuinely separate benefit periods that happen to pay the same amount collapse into one, so it fixes the symptom by deleting real money.COUNT(DISTINCT case_event_id)is legitimate because ids are unique;SUM(DISTINCT)over a non-unique measure is almost never correct. - Keep every total in BIGINT minor units through the whole pipeline and divide only at render. A cast to float or a language-side
NUMERICrounded by the default rule reintroduces exactly the error the integer representation was chosen to avoid.
Follow-up
- A reversal arrives in the following quarter for a benefit period inside this one. Which quarter's total moves, and how do you present a figure that changes after the books were shown to someone?
- Rewrite the instruction branch as a LATERAL subquery instead of a CTE. Does the plan change, and does the correctness argument?
- The report must also show cases with no payments at all. Which join becomes wrong if you move a predicate from the CTE's WHERE into the outer WHERE?
How many barbershops would you place in a city with a population of 1 …
How many barbershops would you place in a city with a population of 1 million people?
Approach
- Say what you would check first and why it is the highest-information step.
- Clarify what is being asked and what a complete answer contains.
- State your assumptions explicitly before working the problem.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Describe your work experience with the technology.
Describe your work experience with the technology.
Approach
- Clarify what is being asked and what a complete answer contains.
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Can you give me an example on how you would build a clock using Python…
Can you give me an example on how you would build a clock using Python?
Approach
- Clarify what is being asked and what a complete answer contains.
- Work from the requirement backwards to the design.
- Say what you would check first and why it is the highest-information step.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Gate an adverse action on notice dispatch across a service boundary
An adverse determination may not take effect until its notice has been generated, dispatched and aged by a statutory notice period counted in the jurisdiction's business days. Rendering and dispatch live in the Notice and Correspondence Service; the effective date lives on the determination. The print vendor accepts one batch a day before a hard cutoff and may accept 400 of 500 items. The caller is the adjudication workflow, which retries on timeout. Design the API between the two services so no crash leaves an action in effect without a notice, or a notice with no resulting action. Deliver the resource lifecycle, the status codes and the partial-batch response.
Approach
- Refuse the synchronous shape first. A single POST that renders, dispatches and flips the effective date has a window where the caller times out after the flip and retries, and another where the process dies after the render and before the flip. The ordering must be render, confirm dispatch, then flip — and the flip is driven by the persisted dispatch fact, not by the response to the call that requested it.
- Model the notice as a resource with its own lifecycle — requested, rendered, queued, dispatched, failed — created by POST /notices returning 202 with a Location and a Retry-After. The determination's effective_on stays NULL until a dispatch event arrives; nothing computes now-plus-n-days at request time.
- Key creation on the business fact (determination_id, notice_type, template_version) with a unique constraint, so a retried POST returns the existing notice instead of rendering a second legal artifact with a different generation timestamp. The rendered bytes are themselves evidence, so two renders is two documents, not one operation done twice.
- Represent the batch honestly. A vendor accepting 400 of 500 is not one status: return 200 with a per-item array keyed by notice_id, each carrying its own status and error code. Avoid 207, which is defined for WebDAV in RFC 4918 and reaches general HTTP clients as an unrecognised 2xx, and never collapse the batch to a boolean that makes the caller resubmit all 500.
- Make the missed cutoff a first-class outcome with its own code, distinct from a vendor rejection. An item that misses the window is queued for the next cut and its effective date moves a business day; a design that silently keeps the original date lets an adverse action take effect before its notice period has elapsed.
- Compute the aging in civil time over a versioned holiday calendar: convert the dispatch instant to the jurisdiction's zone, then walk business days. Adding 86,400-second intervals to a UTC instant is wrong across a DST transition and ignores a holiday list amended year to year, and the error direction that matters lands the flip a day early.
Worked solution 35 min
- Draw the two-service sequence with four crash points marked — before render, after render before queue, after queue before vendor acknowledgement, after acknowledgement before flip — and write what recovery does at each.
- Define the notice resource states and legal transitions plus the unique key (determination_id, notice_type, template_version).
- Write the 202 and Location contract and the dispatch event the determination consumes to set effective_on.
- Write the per-item batch response for 400 accepted and 100 missed-cutoff items, with distinct codes for vendor-rejected and missed-cutoff.
- Compute effective_on for a dispatch at 23:50 local the day before a holiday that falls on a Sunday and is observed on the Monday, and compare against a manual count.
Follow-up
- The dispatch event is delivered twice. What stops the effective date being computed twice, and does a second identical computation actually matter?
- A notice renders, electronic delivery bounces, and the print fallback goes out the next day. Which dispatch starts the clock?
- An appeal fourteen months later needs the same notice bytes. What must have been pinned at render time for that to be possible?
Two current determinations survive a partial unique index
About twice a week a case has two determination rows with is_current true for one (case_id, reopen_cycle), which UNIQUE (case_id, reopen_cycle) WHERE is_current should make impossible. It has never reproduced in staging, and a build with extra logging ran clean for a week, so the team is calling it a concurrency heisenbug and proposing an advisory lock. The determination table was range-partitioned on decided_at six months ago. Deliver an ordered checklist, state the single query you run first, and explain precisely what its result rules out.
Approach
- Run the discriminating query before adopting anyone's theory: for each offending pair, select both rows' decided_at, decided_by, rule_version_id, supersedes_determination_id and the partition each row physically lives in. The spread in decided_at settles it — milliseconds apart is a genuine race, months apart cannot be one, and no amount of locking would have prevented it.
- Verify the constraint is real and enforcing. List indexes on the parent and on every partition, and check pg_index.indisvalid and indisready: a CREATE INDEX CONCURRENTLY that failed leaves an index present in the catalog, visible in tooling, and enforcing nothing. This costs one query and eliminates a whole class.
- Check the partitioning interaction, which is the likely answer. A unique index on a partitioned table must include every partition key column, so a partial unique index on (case_id, reopen_cycle) alone cannot exist on the parent; it was almost certainly created per partition instead. Per-partition uniqueness permits exactly one current row per partition, so an original determination and a correction re-run months later fall into different partitions and both stand.
- Explain both pieces of the folklore with that mechanism. Staging never reproduced it because seeded data occupies one partition, where the constraint does hold. The logging build proved nothing because the mechanism is not timing-dependent, and a week without an occurrence is entirely consistent with a twice-weekly rate.
- Fix by moving the invariant somewhere it can be global: either partition on something functionally determined by case_id so every row for a case shares one partition, or hold the invariant in a small unpartitioned current_determination table with UNIQUE (case_id, reopen_cycle) and a foreign key to the determination row, written in the same transaction as the supersession.
- Then backfill deliberately: resolve each existing duplicate pair by following supersedes_determination_id, not by ordering on decided_at, because a corrected determination can legitimately carry an earlier effective date than the one it supersedes. Record what was changed, since some of those cases have already been noticed and appealed.
Follow-up
- You switch to hash partitioning on case_id. What does that cost the archival job that currently drops old partitions by date?
- During the backfill, what does the read API return for a case that currently has two current rows?
- Some of these cases were noticed under the wrong current determination. What does correcting them require beyond a database change?
Four days sample coding, design, fundamentals and the practical rounds at deliberately shallow depth, which is enough to surface the topics you did not know were in scope. That map, rather than a guess made on day one, decides where the last three days go.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Coding, one pass at shallow depth
- Solve one problem from each of six families, an array with two pointers, hash counting, binary search, a tree traversal, a graph traversal and one dynamic program, under a hard twenty-minute cap with no extensions, marking each finished, late, or stalled.
- For every stall, write the exact move you could not make rather than the subject, so the note reads could not turn the recurrence into a loop rather than bad at dynamic programming.
- Fix nothing today. The value of the pass is the unfixed record.
Deliverable: Six timed attempts marked finished, late or stalled, each stall carrying a named blocking move.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Design, one pass at shallow depth
- Spend twenty minutes each on three different shapes, a read-heavy feed, a write-heavy ingest path, and something needing a transaction across two entities, stopping each at requirements, interface and data model.
- After each, write the first question you could not answer, which is usually a number you could not estimate or a failure mode you had no vocabulary for.
- Mark which of the three you would be most relieved not to be asked, and treat that as data rather than as a preference.
Deliverable: Three shallow designs, each with the first unanswerable question written at the bottom.
Practice prompt ↗Practice prompt ↗03Fundamentals and the practical rounds
- Answer eight short questions in writing at four minutes each, covering the material that fills the gaps between the big rounds: what happens between a URL and a rendered page, what an index costs on write, when a process is preferable to a thread, and what conditions a deadlock requires.
- Do one thirty-minute practical task of the kind a take-home compresses: read an unfamiliar two-hundred-line file and write what it does, what you would change, and the one thing you remain unsure of.
- Score every answer fluent, correct but slow, or absent, and keep the absent ones visible.
Deliverable: Eight scored short answers and one written reading of unfamiliar code.
Practice prompt ↗Practice prompt ↗04The rounds that are about you, and the map
- Deliver three behavioural answers aloud against a timer, a conflict, a failure you owned, and a decision made without enough information, marking any that ran past three minutes or contained no number.
- Assemble the map: every marked item from days one to three on a single page, sorted by how likely it is to appear in your loop rather than by how uncomfortable it felt.
- Choose exactly two areas for the remaining three days and write down what you are deliberately abandoning.
Deliverable: A one-page scored map of the whole surface area with two areas chosen and the rest explicitly abandoned.
Practice prompt ↗Practice prompt ↗Worked solution ↗05First chosen area, to the depth you skipped
- Work the higher-ranked area in four focused blocks, choosing items one level above where you stalled rather than repeating what already works.
- After each block write the rule you extracted in one sentence with its precondition attached, since a rule carrying no precondition is exactly what fails under a variation.
- Re-attempt the day-one or day-two item that exposed this area and compare against the original timing.
Deliverable: Four worked blocks, a timed re-attempt against the original, and three one-sentence rules with preconditions.
Practice prompt ↗Practice prompt ↗06Second chosen area, where the gap is coverage rather than speed
- Treat the second area differently from the first. Day five drilled something you could already half-do; this one is usually a topic you had simply never met, so build one worked reference example end to end and keep it, rather than attempting six problems badly.
- Write down the vocabulary you were missing on day two or three, five terms at most, each with the one sentence that makes it usable in an answer rather than the textbook definition.
- Redo the shallow attempt that exposed this area and note whether you now fail later in the problem, because moving the failure point is the realistic gain from a single day and is worth more than a score that did not change.
Deliverable: One worked reference example for the newly covered area, a five-term vocabulary list, and a note on where the failure point moved.
Practice prompt ↗Practice prompt ↗07Reassemble the loop
- Sit two rounds back to back with no gap, ordering them so the area you chose second comes last, because the map was built from rested, isolated attempts and the loop will reach your weaker area when you are already spent.
- Write where the second round suffered from the first, which is normally the point at which structure collapses into narration.
- Reduce the week to one page holding only the rules you can state without reading them.
Deliverable: Mock notes on cross-round carryover plus a one-page card of rules you can recite from memory.
Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Engineers over-index on what they repaired. A stronger answer covers something you knowingly left broken: the alert you tuned down, the data inconsistency you documented instead of chasing, the cleanup you deferred past two quarters. Give the reasoning and the condition that would have reopened it, so it reads as a decision and not as neglect.
What is your experience level using Kibana?
What is your experience level using Kibana?
Approach
- Close with what you would do differently, concretely.
- State the situation in two sentences and spend the rest on the reasoning.
- 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?
Unblock an engineer whose replay creates duplicate determinations
An engineer's bulk replay job, re-running determinations after a rule correction, has left some cases with two rows flagged current and has re-issued notices for cases whose outcome did not change at all. They have been on it for two days and are now proposing a cleanup script to delete the extra rows. Describe unblocking someone in this shape: how you found where their model was wrong, what you had them do first, and how you left them able to handle the same class of bug without you.
Approach
- Get the invariant said out loud before anyone touches code. 'A replay that changes nothing writes nothing' is usually the sentence they have not yet said, and saying it reframes the problem from a concurrency puzzle into a missing no-op check, which is a different and much smaller fix.
- Separate the two failures they have merged into one bug. Duplicate current rows are a concurrency defect the database should have rejected; re-noticing unchanged cases is a logic defect in the job. A cleanup script addresses neither, and running it before the constraint exists guarantees running it again next week.
- Have them reproduce the smaller failure themselves — two concurrent inserts against a table with no partial unique index — rather than describing it. A reproduction they built transfers to the next bug; a diagnosis handed to them does not.
- Be explicit about what you deliberately did not do: you did not take the keyboard, and you did not let the cleanup script go first. Say how you decided that, because with an incident running the wrong answer is to teach instead of to stop the bleeding, and the judgement call is the interesting part.
- Close the loop on repeatability for them: a no-op predicate compared before writing, a dry-run mode whose output is counts by reason code, and agreement on who reviews the next replay before it runs.
Follow-up
- Notices already went to constituents whose determination did not change. What are they told, and who writes it?
- How do you tell whether the duplicate rows came from concurrency or simply from the job being run twice?
- What changes in your approach if an auditor found this rather than the engineer?
Own an outage where actions took effect without notices
An overnight job moved 4,200 cases into a suspended status whose statutory notice period had never started: the render step failed, the print vendor's daily cutoff passed, and the effective-date flip ran on a timer instead of on the dispatch event. Describe an incident of this shape that you owned. State how you detected it, how you bounded it while the clock kept running, what you could and could not roll back, what the affected people were told, and the durable change that made the flip depend on dispatch.
Approach
- Open with blast radius in the units the obligation is written in, not in technical ones: how many cases flipped, how many of those had an action that already took legal effect, how many had money stop. Then state the detection gap in minutes between the timer firing and anyone knowing, and say honestly if the only signal was a constituent phone call.
- Split what is reversible from what is not before describing any fix. Restoring the prior status is reversible, but it is done by appending a corrective transition to case_event rather than by updating or deleting the erroneous one, because that log is append-only and the wrong transition is itself part of the record now. A suppressed payment is recoverable by issuing the instruction; an action that has already had legal effect on someone is not undone by a status column.
- Name the ordering you violated and the ordering you restored: render, confirm dispatch, then flip, with the flip consuming the dispatch event. A timer fires whether or not the letter exists, so the timer is the defect and the render failure is only what exposed it.
- Re-notice with a fresh statutory clock rather than back-dating the period to when the letter should have gone out. Back-dating is the tempting shortcut and is precisely what an appeal will find, since the dispatch record per channel contradicts it.
- Close with a durable instrument, not a resolution: an alarm on the count of cases sitting in a gated state with no matching dispatch row beyond a threshold age, and the vendor cutoff tracked as its own objective, because missing it shifts a statutory date by a full business day.
Follow-up
- The render queue is 40 minutes from the cutoff and behind. Do you cut a partial batch or hold everything to the next day, and who decides?
- A constituent appeals citing the notice date. What must the data model produce to reconstruct what actually happened, and in what order?
- How would this have been caught without a complaint from someone affected?
- 01
What is your experience level using Kibana?
- 02
An engineer's bulk replay job, re-running determinations after a rule correction, has left some cases with two rows flagged current and has re-issued notices for cases whose outcome did not change at all. They have been on it for two days and are now proposing a cleanup script to delete the extra rows. Describe unblocking someone in this shape: how you found where their model was wrong, what you had them do first, and how you left them able to handle the same class of bug without you.
- 03
An overnight job moved 4,200 cases into a suspended status whose statutory notice period had never started: the render step failed, the print vendor's daily cutoff passed, and the effective-date flip ran on a timer instead of on the dispatch event. Describe an incident of this shape that you owned. State how you detected it, how you bounded it while the clock kept running, what you could and could not roll back, what the affected people were told, and the durable change that made the flip depend on dispatch.
Is this an official Omni Federal interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Omni Federal. Rounds and questions reflect what candidates have reported, not a process Omni Federal has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How long does the hiring process typically take?
The process is generally efficient, often moving from the initial screen to a final decision within a few weeks. However, because of the nature of project-based hiring, timelines can fluctuate.
PracHub interview research ↗What is the best way to prepare for the technical interview?
Focus on your core competencies and be ready to explain your past projects in detail. Since the technical interviews often involve team members, be prepared to discuss trade-offs in your design choices.
PracHub interview research ↗Does the company prioritize culture fit?
Yes, Omni Federal values a "get things done" attitude. They look for individuals who are self-driven, communicative, and comfortable working in a fast-paced environment where priorities can shift based on contract needs.
PracHub interview research ↗Are there remote or hybrid options?
Job postings often specify location requirements, such as Onsite in locations like Chantilly, VA. Always clarify the specific location expectations for the team you are interviewing with.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22