As a Software Engineer at Municipal Property Assessment, you play a vital role in maintaining the integrity and accuracy of property data that serves as the foundation for municipal taxation and local government planning. This position is not just about writing code; it is about building reliable, scalable systems that handle complex datasets and provide essential services to the public sector. You will contribute to the modernization of digital infrastructure, ensuring that property assessment processes are efficient, transparent, and data-driven.
The work you perform directly impacts how stakeholders interact with property data, requiring a balance of technical precision and an understanding of business logic. You will engage with both frontend and backend systems, often working within a collaborative team environment to solve real-world problems. Whether you are optimizing database performance, integrating cloud services, or designing API solutions, your efforts ensure that Municipal Property Assessment remains a leader in public sector technology.
This role offers a unique opportunity to work on high-impact projects that require a blend of software engineering rigor and thoughtful system design. You can expect a professional environment where technical curiosity is valued and where your ability to communicate complex solutions to non-technical stakeholders is just as important as your mastery of your primary programming language.
Initial Screening
reportedThe title covers product work, platform work, infrastructure, mobile and frontend, and those are different jobs with different loops behind them. A screening call is the cheapest place to find out which one the seat is, and asking reads as experienced rather than fussy. The questions that separate them: what the team is on call for, what the last three projects were, and whether any round happens inside an existing repository instead of a blank file. Then say which of that you have done and which you have not. Claiming the whole posting is the fastest way to be found out one round later.
What to demonstrate
- Whether you can locate your experience inside one flavour of the role honestly instead of claiming the entire requirements list
- Whether you name what you have not done, which an experienced screener reads as a level signal and can plan the loop around
- Whether what you want next matches what the seat is: someone who wants greenfield work landing on a team that mostly operates an existing system is a hire that leaves within the year
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
- Split your last two years into rough percentages across feature work, operating and debugging live systems, and design or review, so a question about scope gets numbers rather than adjectives
- Bring three questions that discriminate between seats: what the team is paged for, how much of the work is changing existing code versus standing up something new, and what shipped in the last quarter
Primary Interview
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.
Treating an integration partner as if it were a synchronous API when the system of record is a nightly batch
The effective consistency model is 'as of last night', so a screen that shows a constituent their updated status immediately after a submit is telling them something the authoritative system will not agree with for hours, and a caseworker who acts on it creates a conflict that surfaces as a reconciliation exception nobody owns. Read-after-write expectations also encourage retry-until-consistent loops that hammer a mainframe window sized for one pass. Make staleness explicit in the model and in the interface - show the as-of time, keep the local record in a pending state until the batch confirms, and design the reconciliation job as the place where disagreement is resolved rather than as an exception report.
Computing a statutory due date by adding an interval to a UTC timestamp
The deadline is a civil date in a jurisdiction that observes daylight saving, and a civil day is not always 86,400 seconds; the same arithmetic also ignores weekends and a holiday list that is amended annually and differs by jurisdiction. The result is a due date off by a day near a transition, which reports a case as on time when it is late by law - the direction of the error that produces findings rather than complaints. Store the event as an instant, convert to the case's civil time zone, and walk the business-day calendar as versioned data with its own effective dates, then test the transitions and the holidays explicitly rather than the happy path in July.
Hardcoding to the sample inputs
Solve the stated problem rather than the two examples; special-casing a literal to make a sample pass is obvious immediately and reads as either a misunderstanding or an attempt to fake progress. If you genuinely cannot generalise yet, say which part is a stub and what would replace it.
Check-then-act on shared state
Read, decide, write is not safe under concurrency unless the decision and the write are one atomic step: a unique constraint with conflict handling, a compare-and-set, or a row lock held for the whole transaction. Two requests can both pass the existence check before either inserts, which shows up as duplicate rows under load and never in a single-threaded test.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Describe a situation where you performed troubleshooting on a complex …
Describe a situation where you performed troubleshooting on a complex issue.
Approach
- Walk one small example through your approach before writing the whole thing.
- Restate the input: its shape, its size, and what is guaranteed about it.
- 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?
- How does this change if the input no longer fits in memory?
What is a significant problem you faced in a previous project, and how…
What is a significant problem you faced in a previous project, and how did you solve it?
Approach
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- 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?
Explain your favorite project: what was your specific role and what ch…
Explain your favorite project: what was your specific role and what challenges did you overcome?
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
- Name the brute-force solution and its complexity before improving on it.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Match a rail return file onto payment instructions in one pass
You hold 400,000 disbursement_instruction rows for a 90-day window (instruction_id, determination_id, benefit_period_start, amount_minor, rail_reference, status) and a return file of 12,000 rows carrying rail_reference, amount_minor, return_code and returned_at. The rail guarantees rail_reference is unique only within 90 days and recycles values afterwards, and it may resend a return it already sent. Produce three buckets: returns matched to exactly one instruction, returns matching none, and returns matching more than one. One pass over each input. State your time and space bounds.
Approach
- Build one hash map from rail_reference to a small list of instruction_ids in a single pass over the instruction rows. Lists, not scalars: recycling means a reference can legitimately collide across the window edge, and you need to observe that rather than let the last writer win. O(n) time, O(n) space for n=400k references.
- Stream the return file and probe. Zero hits goes to unmatchable, one hit to matched, more than one to ambiguous. Do not disambiguate an ambiguous hit by amount_minor: a returned payment and a recycled reference can carry the same amount, and guessing turns a reportable exception into a wrong ledger entry.
- Deduplicate resends on the business fact, not on the file row. A return is uniquely identified by (instruction_id, return_code, returned_at) once matched; a second identical row applies the same compensating state and must be a no-op, which is what makes replaying a redelivered file safe.
- Do not filter the instruction side by rail_reference IS NOT NULL. A NULL reference means the acknowledgement has not been processed, not that nothing was sent, so those rows belong in the map's absence set and drive the separate unacknowledged-but-submitted report.
- Memory: 400k entries of a ~20-byte reference key plus an 8-byte id is roughly 11 MB before hash overhead, comfortably in process. If the window ever widens past what fits, range-partition by the reference prefix and run k passes at k times the read cost rather than reaching for a database join per return row.
Worked solution 20 min
- Build an eight-row instruction fixture: six with distinct references, and two sharing reference R because the rail recycled it 91 days apart.
- Build a five-row return file: three matching distinct references, one naming reference R, one naming a reference never assigned.
- Run the two passes and record which bucket each return lands in.
- Append a byte-identical copy of one already-matched return row and re-run, confirming the applied state is unchanged.
Follow-up
- The rail sends a partial return for less than amount_minor. What does your matcher do, and what does the instruction row become?
- A return arrives for an instruction that has already been reversed by a compensating row. How do you tell a duplicate return from a genuine second event?
- You must run this continuously rather than per file. What bounds the map now, and what is the eviction rule?
Add a uniqueness rule to a live payments table with duplicates
disbursement_instruction(instruction_id BIGSERIAL PK, determination_id BIGINT, benefit_period_start DATE, amount_minor BIGINT, status TEXT, reversal_of_instruction_id BIGINT NULL) has 40M rows and takes writes continuously. It was built without UNIQUE (determination_id, benefit_period_start); a retried batch created 11,400 duplicate pairs, and 3,900 of those duplicates reached settled. Money that moved is never deleted and never voided — it is unwound with a compensating reversal row carrying reversal_of_instruction_id, which repeats the same business key. status values include voided. Produce the migration: the query that finds the duplicates, what you do with the ones that settled, the DDL that adds the constraint without blocking writers, and the deploy ordering. Name the lock each statement takes and what happens when it cannot be acquired.
Approach
- Find the duplicates with a window rather than a self-join:
SELECT instruction_id, status, ROW_NUMBER() OVER (PARTITION BY determination_id, benefit_period_start ORDER BY instruction_id) AS n FROM disbursement_instructionand inspect every row withn > 1together with its status, because the remediation differs entirely by status. Then = 1row is the one that stays live; the rest are what you unwind. - Do not make the data fit the constraint by deleting rows. A duplicate that reached
settledmoved real money and the rail's own ledger will not forget it; deleting the row makes your records disagree with the counterparty. The 7,500 unsent duplicates may be set tovoided. The 3,900 settled ones get compensating reversal rows referencing them viareversal_of_instruction_id— and stay. - That remediation is what rules out the obvious predicate. After it, each settled duplicate key still holds three non-voided rows: the original, the settled duplicate and its reversal.
CREATE UNIQUE INDEX CONCURRENTLY ... WHERE status <> 'voided'therefore aborts with 23505 on the first of the 3,900. The fact the predicate needs — 'this row has been unwound' — cannot be a subquery either: a partial index predicate may reference only columns of the row being indexed and must be IMMUTABLE. So the fact has to be written onto the row. - Add it as a nullable column with no default, which is a catalog change and not a table rewrite (PostgreSQL 11 extended that to non-volatile defaults as well):
ALTER TABLE disbursement_instruction ADD COLUMN reversed_by_instruction_id BIGINT. It still takes ACCESS EXCLUSIVE for the catalog write, so it carries the samelock_timeoutguard as any other ACCESS EXCLUSIVE step; add the self-referencing foreign key separately asNOT VALIDand thenVALIDATE CONSTRAINT, which takes only SHARE UPDATE EXCLUSIVE. - The constraint is then a partial unique index over the rows that are live originals:
CREATE UNIQUE INDEX CONCURRENTLY uq_instr_business_key ON disbursement_instruction (determination_id, benefit_period_start) WHERE status <> 'voided' AND reversal_of_instruction_id IS NULL AND reversed_by_instruction_id IS NULL. Each conjunct does one job — never sent, is itself an unwind, has been unwound. Accept the consequences: a partial index cannot back anALTER TABLE ... ADD CONSTRAINT ... UNIQUE USING INDEX, so there is no named constraint and no foreign key can reference this key, andINSERT ... ON CONFLICTmust repeat all three conjuncts in its inference clause. - Prove the data fits before you build. Run
SELECT determination_id, benefit_period_start FROM disbursement_instruction WHERE <the index predicate> GROUP BY 1,2 HAVING count(*) > 1and require zero rows. A unique build that hits a violation is not free:CREATE INDEX CONCURRENTLYdetects it in the second pass, aborts after scanning 40M rows twice, and leaves an index withindisvalid = falsethat must be dropped withDROP INDEX CONCURRENTLYbefore retrying. - Name the locks.
CREATE INDEX CONCURRENTLYtakes SHARE UPDATE EXCLUSIVE, so readers and writers continue; it makes two passes plus waits for concurrent transactions and cannot run inside a transaction block. A plainCREATE INDEXor anALTER TABLEvariant takes ACCESS EXCLUSIVE, which queues behind any running query and blocks every reader that arrives behind it in the queue — a five-millisecond statement becomes an outage while one long report finishes. Guard every ACCESS EXCLUSIVE step withSET lock_timeout = '2s'and retry in a loop, so a failed acquisition ends as a failed migration step instead of a stalled table. - Order the deploy so the window is never open: add the column; ship the application code that derives the idempotency key from
(determination_id, benefit_period_start), treats 23505 as a converged retry, and stampsreversed_by_instruction_idwhenever it writes a reversal; remediate the existing duplicates in chunks; re-run the residual-duplicate check; build the index concurrently; verifyindisvalidinpg_index. Building the index before the code can handle a violation converts every legitimate retry into a user-visible error.
Follow-up
- The concurrent build fails at 90% because of a deadlock with a nightly batch. What is on disk now, and what exactly do you run before retrying?
- A duplicate settled and then the original was returned by the rail. What does the compensating row look like, and what is the account's net position?
- Once the partial index exists, how does the batch writer's
ON CONFLICTinference clause have to be written against a three-conjunct predicate, and what happens if the predicate is omitted?
Diagnose why the overdue-case queue scans four million rows
case holds 4M rows, 2.6M of them closed, and idx_case_status ON "case"(status) is the only relevant index. The queue query is SELECT case_id, sla_due_on FROM "case" WHERE program_code = $1 AND status IN ('submitted','evidence_pending','in_review') AND sla_due_on <= CURRENT_DATE + 3 ORDER BY sla_due_on LIMIT 50. EXPLAIN (ANALYZE, BUFFERS) shows a sequential scan followed by a top-N sort, 900 ms. Explain why the existing index is not chosen, propose the index you would build, and state what you check in the new plan.
Approach
- Start with selectivity, not with the index definition.
statushas seven values and the three open ones cover roughly 1.4M of 4M rows; an index whose leading column selects 35% of the table costs more than a sequential scan once random heap fetches are priced in, so the planner is making the correct decision given what it has. - Read the numbers, not the shape: compare each node's estimated rows to actual rows in
EXPLAIN (ANALYZE, BUFFERS). A tenfold or worse gap on the conjunction ofprogram_codeandstatuspoints at correlation the planner assumes away, whichCREATE STATISTICS case_prog_status ON program_code, status FROM "case"plusANALYZEcan correct. - Build the index the query actually wants:
CREATE INDEX CONCURRENTLY idx_case_open_due ON "case" (program_code, sla_due_on) WHERE status IN ('submitted','evidence_pending','in_review'). Equality column first so it fixes a prefix, range and sort column second so the index scan delivers rows already ordered bysla_due_onand the LIMIT 50 stops after 50 heap fetches instead of sorting a large intermediate. The partial predicate drops the 2.6M closed rows out of the index entirely, which is most of its size. - Spell the query's predicate exactly as the index predicate is spelled. The planner will only use a partial index when it can prove the query implies the index predicate, and relying on it to derive that from a differently phrased condition is how a supposedly indexed query quietly regresses after a refactor.
- Fold the row-level security qual into the index. Every query against this table carries the jurisdiction policy predicate; if
jurisdiction_codeis not in the index, the policy is a filter applied to rows already fetched from the heap, so the LIMIT reads more rows than it returns. Either add it as a leading column or make it part of the partial predicate, depending on whether one jurisdiction dominates. - Verify with the plan rather than the wall clock: you want an Index Scan (not Bitmap Heap Scan, which loses the ordering and forces the sort back), no Sort node above it, and buffer counts in the tens rather than the tens of thousands.
Worked solution 30 min
- Generate 4M rows with a realistic status skew and run the query under
EXPLAIN (ANALYZE, BUFFERS); record the node types, the estimated-versus-actual row counts and the shared-block reads. - Add the single-column index on
sla_due_onfirst and re-plan, to see the planner either ignore it or choose a bitmap scan that still sorts. - Build the partial composite index concurrently and re-plan; confirm the Sort node disappears and the scan stops early under the LIMIT.
- Rephrase the query's status predicate (for example as three ORed equalities) and re-plan to see whether the partial index is still matched.
- Enable the row-level security policy and re-plan to see the policy qual appear, then fold
jurisdiction_codeinto the index and compare buffer counts.
Follow-up
- A supervisor adds
ORDER BY sla_due_on, case_idfor stable pagination. Does your index still avoid the sort, and if not, what changes? - The same index is now the largest on the table and the write path does 1,500 transitions per second. What does maintaining it cost on UPDATE, and does a HOT update avoid it?
- How does the plan change when
$1is a program holding 90% of open cases, and what does that do to a generic plan cached by the prepared statement?
How do you go about improving the performance of an application?
How do you go about improving the performance of an application?
Approach
- State your assumptions explicitly before working the problem.
- 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.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
What is polymorphism and how does it apply to hierarchical structures?
What is polymorphism and how does it apply to hierarchical structures?
Approach
- Work from the requirement backwards to the design.
- State your assumptions explicitly before working the problem.
- Clarify what is being asked and what a complete answer contains.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Gate an adverse effective date on confirmed notice dispatch
An adverse determination may not take effect until its notice has been generated, dispatched, and aged by a statutory period counted in the jurisdiction's business days. Rendering, dispatch, and the effective-date flip live in three services. Volume is 1 to 2 million notices a month across electronic delivery, a print vendor, and secure message; print batches cut once daily against a hard vendor cutoff. Design the path, then state exactly what the system does when the print vendor endpoint is unreachable for the four hours spanning the cutoff. Deliverable: ordering, event contract, failure behaviour.
Approach
- Fix the ordering and make the seam crash-safe. Render from a pinned template version into immutable bytes, persist the notice row and an outbox row in one local transaction, dispatch per channel, and flip the effective date from the dispatch event. A timer started at render fires whether or not the letter exists, which is how an adverse action lands on someone who was never told.
- Model dispatch as a set of per-channel facts, not a boolean. A constituent may be enrolled in electronic delivery and still be owed a printed copy, so the gate releases on the channel the statute names, not on whichever channel happened to succeed first. Each channel carries its own dispatch record and its own retry state.
- Compute the effective date in civil time over versioned calendar data. Convert the dispatch instant to the jurisdiction's zone, then walk a business-day table that has its own effective dates, because holiday lists are amended annually and differ by jurisdiction. Adding ten times 86,400 seconds to a UTC instant is wrong across a daylight-saving transition and ignores weekends entirely, and the error direction that matters is the one that reports a late case as on time.
- Under the named failure, choose correctness over throughput. The bytes are rendered and durable but dispatch is unconfirmed, so the flip does not happen and every affected action slips one business day. That is a visible, explainable, defensible outcome. Flipping on render instead would apply adverse actions to people with no notice, and no amount of later dispatch repairs the interval in which the action was in force.
- Make the slip cheap and auditable. Hold the batch in the outbox with the cutoff as a deadline alarm, publish the count of notices that missed it, and carry them in the next day's batch with dispatch timestamps set to actual dispatch. Backdating a dispatch record to meet the deadline falsifies the artifact that is under appeal.
Worked solution 30 min
- Write the transaction boundary: notice row and outbox row committed together, and enumerate what the outbox payload has to carry for the dispatcher to be stateless.
- Define the dispatch event and the consumer that flips the effective date, stating which service owns each write.
- Implement the effective-date computation by converting the dispatch instant to the jurisdiction zone and walking a versioned business-day table; test a daylight-saving transition and a holiday observed on the following Monday.
- Write the outage runbook: rendered-but-undispatched inventory, the cutoff alarm, the count that slips, and the constituent-facing consequence.
Follow-up
- The vendor returns and confirms it did receive yesterday's file. How do you avoid printing and mailing it twice?
- Which notices, if any, may still take effect on schedule during the outage, and what distinguishes them?
- A supervisor asks you to set the dispatch timestamp to the intended cutoff so the deadline is met. Name precisely what that breaks.
Eligibility p95 spikes to seconds on a fifteen-minute cadence
Eligibility Service caches rule versions and rate tables in process with a 15-minute TTL; a cold load is about 2.5 s and reads roughly 40 MB. Rule versions are published append-only — a correction inserts a new rule_version row and supersedes the old one — and corrections are routinely backdated, republishing the governing version for a statutory_date already in the past. At intake peak — 4,000 evaluations per minute across 12 pods — p95 jumps from 180 ms to 4 s for about 20 seconds, roughly every 15 minutes, with a matching connection spike on the reference database. No request errors, no deploys. Deliver an ordered checklist, explain why the period matches the TTL and why all 12 pods spike together, and give a fix that removes the periodic reload without ever letting a superseded ruleset reach a determination.
Approach
- Plot cache miss rate and upstream query rate, not latency. A spike period equal to the TTL identifies expiry; a spike period tied to traffic shape would move with traffic. Confirm the spike width is close to the cold-load duration under contention rather than to any traffic feature.
- Explain the alignment: a TTL starts when the key is first populated, and all 12 pods populated within seconds of one rolling deploy, so every pod expires in the same second thereafter. Nothing in the design decorrelates them.
- Quantify the herd. At 4,000 per minute across 12 pods each pod takes about 5.6 requests per second; during a 2.5 s cold load roughly 14 requests per pod arrive on the missing key, and without single-flight each issues its own load. That is about 170 concurrent 40 MB reads, near 7 GB in a burst, which is what saturates the reference store's connections and turns 2.5 s of load into 4 s of queueing.
- Fix layer one, inside the pod: single-flight per cache key so exactly one loader runs and the other 13 requests wait on it. This alone cuts the fleet's concurrent loads from about 170 to 12.
- Fix layer two, the better one here: split the cache and key the big half by rule_version_id. Those contents are immutable only under a precondition worth saying out loud — publication is append-only, so a correction writes a new rule_version row rather than editing one in place. Given that, a version-keyed entry can never go stale, needs no expiry at all, and is evicted only for capacity. That is the 40 MB, and it stops expiring on a cadence. What is left is the small half: the resolution from (jurisdiction_code, statutory_date) to rule_version_id.
- Get the resolution's invalidation right, because the intuitive reasoning is wrong in this system: a resolution for a date in the past is not immutable. A backdated correction republishes the governing version for dates already decided, so an entry cached forever on the grounds that the date has passed keeps handing back a superseded rule_version_id, with nothing in any latency graph to flag it. Invalidate on publication instead of leaning on expiry: bump a ruleset_epoch counter in the same transaction that publishes a version, and key resolutions as (ruleset_epoch, jurisdiction_code, statutory_date) so one publish orphans every stale resolution at once and each pod re-resolves only the dates it actually touches. The epoch is one integer to poll on a few-second interval or push on a notification channel; keep a short jittered TTL underneath only as a backstop for a missed notification, sized as the staleness you are willing to decide under rather than as a cache-tuning number. Serve-stale is safe on the version-keyed entries and never on a resolution — that one is a determination under the wrong ruleset, a correctness bug, not a latency one.
Follow-up
- The autoscaler adds a cold pod at peak. What protects the reference store during its first 2.5 s?
- Single-flight is per pod, so 12 pods still miss together. When does a shared cache tier earn its own failure mode, and when does it not?
- A correction republishes the governing version for a statutory_date three months in the past, mid-peak. Which cached entries must become unreachable, which stay valid, and what stops all 12 pods reloading 40 MB at the same instant?
Day one measures instead of guessing, under a fixed rubric, and the remaining hours are allocated in proportion to the gaps before any studying begins. The allocation is deliberately not renegotiated midweek, because the area that feels worst on day three is usually the one that is moving.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Diagnostic, scored before you study anything
- Sit a 110-minute diagnostic in four blocks: forty-five minutes on two coding problems, twenty-five on one design prompt taken to interface and data model, twenty of short-answer fundamentals, and twenty delivering two behavioural answers aloud.
- Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct and 0 is stuck, grading the artifact rather than how the attempt felt.
- Allocate days two to five in proportion to 3 minus each block's score, write the allocation down, and commit to leaving it alone.
Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Largest gap: find the boundary rather than the subject
- Split the weakest area into named sub-skills and rate each separately. For coding those are restating the problem, choosing the structure, stating the invariant, turning the invariant into loop bounds, handling empty and single-element input, and accounting for complexity out loud.
- Attempt three items positioned just above where the rating drops off, and for each write the first move you failed to make.
- Re-attempt one of them from blank four hours later with nothing open.
Deliverable: A sub-skill map with the two blocking sub-skills circled.
Practice prompt ↗Practice prompt ↗03Drill the blocking sub-skill by repeating the shape
- Do eight short repetitions of the same shape rather than eight different problems, so what gets practised is the pattern and not the puzzle.
- State the rule you now hold in one sentence, then test it against a case built to break it, a sliding window over an array containing negative values, or a cache-aside read path whose invalidation message is dropped.
- Have someone else read your one-sentence rule and find the precondition you left out.
Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.
Practice prompt ↗Practice prompt ↗04Second gap, plus maintenance on the strongest area
- Run the same sub-skill decomposition on the second-largest gap in half the time.
- Spend twenty-five timed minutes on the block you scored highest, choosing the hardest item you can still finish rather than a warm-up.
- Write whether each area fails you on recall, on setup, or on execution, and set the fix accordingly: repetition for recall, a written checklist for setup, timed work for execution.
Deliverable: A second sub-skill map plus a one-line failure diagnosis for each area.
Practice prompt ↗Practice prompt ↗Worked solution ↗05The gap that is not a skill
- Record one technical and one behavioural answer, then count two things in the playback: seconds before your first clarifying question, and sentences you began without knowing where they would end.
- Practise saying that you do not know, followed by how you would find out, without letting it soften into a guess, and practise stating a complexity or an estimate before being asked for it.
- Redeliver one answer under a hard ninety-second cap, which forces structure ahead of detail.
Deliverable: Two recordings with a counted reduction in time-to-first-question.
Practice prompt ↗Practice prompt ↗06Retest under day-one conditions
- Sit the same 110-minute structure with new prompts of comparable difficulty and score it on the identical rubric.
- For any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
- Write down which single block you would still lose the offer on.
Deliverable: A second scored rubric placed beside the first, with one named remaining risk.
Practice prompt ↗Practice prompt ↗07Full loop under interview conditions
- Run a sixty-minute mock over the two blocks that moved least, with an interviewer briefed to interrupt and change direction mid-answer.
- Write the recovery script for going blank: restate the question, state your assumption, name the first thing you would check.
- Say every rule from the week aloud without reading it, and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive an interruption.
Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.
Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Counting review comments or mentees proves nothing. The useful version is a specific change you approved with a reservation you stated, or one you blocked and the delay that cost. Say which standard you were holding and why it was worth the friction. A mentoring story needs the thing the other person can now do without you.
How do you deal with conflicts within a team?
How do you deal with conflicts within a team?
Approach
- Close with what you would do differently, concretely.
- Give the blast radius: what could have broken, and what you measured.
- 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?
- What did you decide not to do, and why?
How do you present a technical solution to your manager or non-technic…
How do you present a technical solution to your manager or non-technical stakeholders?
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 did you decide not to do, and why?
- What would you do differently if you ran that again?
How do your previous experiences relate to the work we do here?
How do your previous experiences relate to the work we do here?
Approach
- Give the blast radius: what could have broken, and what you measured.
- Pick a story where you made the decision, not one where you watched it.
- Close with what you would do differently, concretely.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
- 01
How do you deal with conflicts within a team?
- 02
How do you present a technical solution to your manager or non-technical stakeholders?
- 03
How do your previous experiences relate to the work we do here?
Is this an official Municipal Property Assessment interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Municipal Property Assessment. Rounds and questions reflect what candidates have reported, not a process Municipal Property Assessment has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗Is the interview process difficult?
Most candidates describe the difficulty as average. While the technical questions require preparation, the interview is often conversational and focused on your real-world experience.
PracHub interview research ↗How long does the process take?
The process is generally efficient, often consisting of a single interview. You can expect a relatively quick turnaround once you have completed your interview.
PracHub interview research ↗Should I focus on coding or system design?
Both are important. You should be comfortable discussing your coding language of choice while also being able to explain how you design systems and structure your projects.
PracHub interview research ↗How hard are interviews at Municipal Property Assessment for a Software Engineer role?
Candidates report the difficulty as average, and most people get through to an offer at a relatively high rate. That points to a competitive but not extremely hard process for this role.
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