Citizen (NY) · Software Engineer
Updated · 2026-10-02

Citizen (NY) Software Engineer
Interview Guide

THE 60-SECOND BRIEF

Citizen (NY) is described in candidate reports as a real-time public safety alert product with a consumer app. The engineering work reported for this role covers systems that take in live location data, incident reports submitted by users and live video streams, plus internal tools that let an operations team verify and dispatch alerts, and the mobile and web clients that receive those updates. Software Engineers are reported to work alongside product managers, operations staff, data scientists and mobile engineers.

This guide is for candidates interviewing for a Software Engineer position at Citizen (NY). It covers the three reported stages (Recruiter Call, Technical Screening, Onsite Interviews), the ten questions candidates report across algorithms, API and system design and web application implementation, the stack the role lists (JavaScript or TypeScript, React, Node.js, REST and real-time APIs, caching and data modelling), and a plan for the week before the loop.

Candidates report three stages over roughly 3 to 5 weeks: a Recruiter Call, a Technical Screening, then Onsite Interviews built around hands-on development, with API design and building a small web application featuring prominently.

Coding interviewsProblem solvingAPI design

37 min read

Browse Software Engineer questions

See the practice prompts

18Practice promptsAcross five skill areas

The product is built around time-sensitive, location-aware data: where an incident is, who is near it, how its status changes, and how quickly a phone or browser learns about it. Candidates describe a role that touches intake of user-submitted reports, delivery of alerts to clients, and tooling for the operations staff who verify and dispatch them. That shape is visible in the reported questions: a rate limiter for bursts of traffic, an expiring cache for alerts, nearest-responder search on a grid, merging overlapping emergency zones, and a push system keyed to location.

The reported questions fall into three groups. Algorithmic questions cover a rate limiter, shortest path or nearest responder on a coordinate grid, an in-memory cache with expiration, and interval merging. API and system design questions cover an incident reporting and tracking API (REST or GraphQL), a geolocation-based push notification dispatcher, and a comments and reactions API for live incident video. Web application questions ask you to build a filterable real-time incident dashboard, a polling map with incident markers, and an incident report form with location tagging and validation.

Candidates report that the loop leans toward building working things rather than whiteboard-only discussion. Recruiter conversations may mention a conventional system design round, but reports say the practical emphasis falls on API design and a rapid web build, so have working code ready as well as diagrams. Prepare in your strongest language for the algorithm questions, and prepare React with TypeScript or modern JavaScript, plus a small Node.js API, for the build questions, since those are the technologies the role lists.

Reports also mention that prompts can be open-ended and that interviewers may suggest simplifying or switching approach part-way through. Practise stating assumptions in one or two sentences, building the smallest end-to-end version first, and adjusting without restarting. The sections below tie each round, question group and day of the plan to that style of preparation.

01

Recruiter Call

reported

Candidates describe this as a short call to line up your background and expectations with the role. No technical questions are reported for it. Use it to learn the shape of the rest of the loop: recruiter conversations are reported to mention a standard system design round, while the loop itself is reported to centre on API design and building a small web application, so ask what format each later stage takes and which language or framework you may use.

What to demonstrate

  • How your background lines up with a role that lists JavaScript or TypeScript, React and Node.js
  • Your expectations for the position and the process
  • Whether you can describe your own projects clearly and concisely

How to prepare

  • Write a short walkthrough of your career that highlights any real-time, location, notification or mobile work, since the product revolves around those.
  • Prepare questions about the format of the technical screen and of each onsite session, including whether you will code in your own editor or a shared one, and whether you may use a framework.
  • Have your timing, location and compensation expectations ready to state plainly.
Citizen (NY) Software Engineer candidate reports ↗
02

Technical Screening

reported

Candidates describe an initial technical assessment of foundational skills. The reported algorithm questions are the closest practice material for it: a rate limiter, shortest path or nearest responder on a coordinate grid, an in-memory cache with expiration, and merging overlapping intervals. Prepare each as working code with tests rather than as a spoken outline, and be ready to state time and space complexity and the edge cases.

What to demonstrate

  • Foundational programming skills and data structure choice
  • Reasoning about time and space complexity
  • Handling of edge cases such as empty input, touching intervals or expired entries
  • Explaining your approach while you write code

How to prepare

  • Implement a sliding window rate limiter and a token bucket, each with an injectable clock so you can test bursts at window boundaries.
  • Build a TTL cache with lazy expiry on read plus a sweep, and add a maximum size with an eviction rule.
  • Write breadth-first search on a grid with blocked cells and a multi-source version that starts from every responder at once, then interval merging that handles touching and nested ranges.
Citizen (NY) Software Engineer candidate reports ↗
03

Onsite Interviews

reported

Candidates describe a series of hands-on development rounds in which you build working interfaces and design real-world APIs. The reported question groups here are API and system design (an incident API in REST or GraphQL, a geolocation push dispatcher, a comments and reactions API for live video) and web application implementation (a filterable incident dashboard, a polling map, a validated report form). Candidates also report being nudged to simplify or pivot mid-problem, so keep your first version small enough to change.

What to demonstrate

  • Working code produced within a limited timeframe
  • API and schema design: payloads, status codes, data modelling
  • Choosing between WebSockets, Server-Sent Events and polling for live data
  • Asking clarifying questions on open-ended prompts and adapting to feedback

How to prepare

  • Keep a project scaffold you can start in minutes: a React app with TypeScript, a fetch layer and a small Node.js endpoint serving mock incidents.
  • Write an endpoint list for the incident API with status codes, an idempotency key for report creation, pagination, and the reported, verified and resolved state transitions.
  • Sketch the push dispatcher end to end: location-bucketed subscriber index, queue, worker fan-out, push provider limits, retries and deduplication.
  • Build the three reported web tasks from scratch: filterable dashboard, polling map with markers, and a form with client-side validation and location capture.
Citizen (NY) Software Engineer candidate reports ↗

PracHub editorial advice for the preparation topics above.

01

A rate limiter that uses a fixed window counter and lets a double burst through at the boundary

Use a sliding window log or a token bucket, and say which one you chose and why. Keep state per key, remove idle keys so memory does not grow without limit, and inject the clock so you can test the boundary case instead of asserting it.

02

A cache whose expiry is only checked when an entry is read

Combine lazy expiry on read with a periodic sweep, or keep a min-heap of expiry times, so dead alerts leave memory. State what happens at capacity and name the eviction rule.

03

Grid, interval and geometry code that fails on its edge cases

Sort intervals by start before merging and test touching ends, nested ranges and a single interval. Mark cells visited when you enqueue them in breadth-first search. Use a distance formula suited to the coordinates in the prompt, and ask whether the grid has obstacles or diagonal moves.

04

An API design that stops at a list of endpoints

For each endpoint give the request and response payload, status codes, pagination and the behaviour of a retried create. Model incident status transitions explicitly, and say how a mobile client on a weak network gets smaller payloads and live updates.

05

A web build that polishes styling while the data flow is half done, or polls without cleanup

Get fetch, state, render, filter and submit working end to end first. Cancel in-flight requests and clear timers on unmount, ignore stale responses, show loading and error states, and add styling last.

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

15 technical prompts0 include a worked solution

Merge overlapping intervals representing active emergency zones.

medium
Algorithmic Problem Solving

Merge overlapping intervals representing active emergency zones.

Approach
  1. Clarify the interval semantics before coding: are endpoints inclusive, so that [1,3] and [3,5] merge? Is the input already sorted? Can start ever exceed end?
  2. Sort by start, O(n log n). Then walk the list once: if the current start <= last merged end, set last end = max(last end, current end). Otherwise, append the current interval.
  3. The max matters because an interval can be fully contained in the previous one. [1,10] followed by [2,3] must stay [1,10], and a bare assignment would shrink it.
  4. Complexity: O(n log n) time, dominated by the sort, and O(n) space for the output, plus whatever the sort uses. If the input is already sorted, the merge pass is O(n).
  5. Test the edge cases: an empty list, a single interval, all intervals overlapping into one, none overlapping, duplicates, and unsorted input.
Follow-up
  • How would you insert one new zone into an already merged, sorted list, and what does that cost?
  • How would you handle intervals arriving as a stream, with the merged set queryable at any time?
  • How would you compute the total time covered by at least one active zone, or the maximum number of overlapping zones?

Collapse a redelivered event batch into per-aggregate high-water marks

easy
hashingat-least-onceaggregation

You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.

Approach
  1. One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
  2. Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
  3. Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
  4. If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.
Follow-up
  • The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
  • How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?

Track a rolling failure rate per destination for circuit decisions

easy
sliding windowring buffercircuit breaker

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

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

The plan starts with a reusable scaffold, then covers the reported algorithm, API design and web build questions in the order candidates meet them, and ends with a full mock. PracHub's practice set supplies extra drills on adjacent skills.

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

Prepare, practise & reflect

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

0 / 7 done
01Map the loop and set up a scaffold
  • Write the three reported stages and, for each, what you still need to learn about its format; send those questions to your recruiter.
  • Create a React and TypeScript project plus a small Node.js server that returns a list of mock incidents with severity, latitude and longitude.
  • List the technologies the role names and mark any you have not used in the last year.

Deliverable: A runnable scaffold that renders mock incidents from a local endpoint, and a written list of format questions for the recruiter.

02Rate limiter and expiring cache
  • Implement a sliding window rate limiter and a token bucket with an injectable clock; test the boundary burst and a quiet key.
  • Implement a TTL cache with lazy expiry, a sweep and a maximum size; test expiry, overwrite and eviction.
  • Do the PracHub drill that tracks a rolling failure rate per destination, then the one about instances that grow in memory until a restart, and relate both to cache and limiter state.

Deliverable: Passing tests for a rate limiter and an expiring cache, with time and space complexity written under each.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗
03Grids, intervals and geometry
  • Write breadth-first search for the shortest path on a grid with blocked cells, then a multi-source version that finds the nearest responder for each cell.
  • Write interval merging and test touching, nested and unsorted inputs.
  • Write a point-in-polygon check with ray casting, since a GPS point against a hazard zone is a reported scenario, and do the PracHub drill on collapsing a redelivered event batch.

Deliverable: Three tested functions (grid search, interval merge, point in polygon) with a list of edge cases for each.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
04Incident API and live video interactions
  • Write the incident API as a spec: resources, endpoints, status codes, idempotent report creation, pagination and the reported, verified and resolved states. Then outline the GraphQL version and name its trade-offs.
  • Design the comments and reactions API for live video: pick WebSockets, Server-Sent Events or polling and justify it, and handle reaction counts under heavy load.
  • Do the PracHub drill that replaces offset paging with keyset paging and apply it to your incident list.

Deliverable: One written API spec for incident reporting and one for live comments and reactions, each with a justified delivery protocol.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
05Geolocation push dispatch
  • Design the dispatcher: how users' locations are stored and bucketed, how an alert's target area becomes a recipient list, and how a queue and workers send it.
  • Add failure handling: push provider rate limits, retries with backoff, deduplication and what happens during a traffic spike.
  • Design the endpoint that accepts batched location updates and say what you would cache or drop to keep it cheap; do the PracHub drill on an index the planner ignores.

Deliverable: A component diagram with the data flow, the storage and queue choices, and a written list of the first three failure points.

Practice prompt ↗Practice prompt ↗
06Build the three web tasks
  • Build the incident dashboard with live refresh and filters for severity and distance from a chosen point.
  • Build the map view with Leaflet that polls the endpoint and adds, moves and removes markers without re-rendering everything.
  • Build the report form with client-side validation, location capture from the browser and a fallback when permission is denied.

Deliverable: Three working screens in the scaffold, each with loading and error states and request cleanup.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
07Full mock and stories
  • Run a timed mock: one API design question out loud, then one web build from an empty folder, narrating assumptions and trade-offs as you go.
  • Rehearse your recruiter call walkthrough and your questions about the loop format.
  • Prepare stories using the PracHub prompts about arguing against a design and turning a code review disagreement into a decision.

Deliverable: A recorded or written mock of one design and one build, a final list of gaps, and two written story outlines.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Practice prompt ↗

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

Candidates do not report specific behavioral questions for this loop, so the prompts below are rehearsal material rather than reported questions. They follow the themes candidates describe: open-ended prompts that need clarifying, feedback or a change of direction during a build, and collaboration with product, operations and mobile colleagues.

Argue against a design, lose, and commit anyway

medium
disagreementservice boundariesdecision records

Describe a design you argued against and lost. State the failure you predicted as a named mechanism, not a feeling about complexity: two services that would need one transaction, a projection with no rebuild path, a write path with no idempotency key. Say what evidence you brought, what the decision maker weighed instead, and what you did after the decision was made: what you instrumented, what you wrote down, and whether the prediction came true. Five minutes.

Approach
  1. State the prediction in falsifiable form up front: the mechanism, the condition that triggers it, and the observable outcome. A prediction that cannot be checked also cannot be credited to you later.
  2. Show the evidence you had at the time and label each piece honestly as measured, analogous, or intuition. Keeping the intuition is fine; disguising it as data is the thing that erodes your standing in the next argument.
  3. Represent the opposing case at full strength, including the constraint you did not control: a fixed date, a team boundary, or the fact that the decision was cheap to reverse and yours was not.
  4. Make disagree-and-commit concrete. Name the artefact you left behind so the prediction could be settled without you: the alert and its threshold, the counter on the dashboard, the decision note that recorded the trade-off and the condition that would revisit it.
Follow-up
  • What threshold on that alert would have proved you right, and did anyone ever look at it?
  • If the same proposal arrived tomorrow with the same deadline, would you argue it the same way?

Narrate an outage you owned from page to postmortem

hard
incident responseblast radiuspostmortems

Pick an incident you personally drove, ideally one where writes were affected rather than reads. In six to eight minutes: state the symptom as it first appeared on a dashboard, the blast radius you established before you knew the cause, the mitigation you applied and when, the mechanism you eventually proved, and the follow-up that would prevent a repeat. Bring numbers: error rate, tenants affected, minutes to mitigate, minutes to resolve. If you cannot name what you measured, choose a different incident.

Approach
  1. Open on the signal rather than the cause: which metric at which percentile moved, on which service, at what time, so the listener follows the same evidence you had rather than a conclusion you already reached.
  2. Separate mitigation from diagnosis out loud. State what you did to stop the bleeding (flag off, shed traffic, drain a lease, roll back a deploy) and say plainly that you did it before the mechanism was known, because those are two jobs with different deadlines.
  3. Establish blast radius in countable terms: how many tenants, how many writes, and crucially whether the effect was loss or only delay. An append-only revision table or a pending outbox row means the change survived and the projection was merely behind, which is a repair rather than a data-loss incident.
  4. Prove the mechanism instead of asserting it. Name the trace span that grew, the plan that flipped to a sequential scan, the lease that expired, plus one alternative you ruled out and the signal that stayed flat while you ruled it out.
Follow-up
  • What would you do differently in the first five minutes, given the same dashboard and no more information?
  • Which follow-up action did you deliberately not take, and why was dropping it the right call?

Turn a code review disagreement into a decision

easy
code reviewoptimistic concurrencycommunication

A colleague's change updates a row with UPDATE resource SET version = version + 1 WHERE resource_id = $1 AND version = $2 and treats an affected-row count of zero as a successful no-op. You read that as a silently lost update; they think returning 200 is friendlier to clients than returning a conflict. Describe how you have handled a review disagreement of this shape: what goes in the comment, when you leave the thread, and who decides. Then write the comment you would leave here, in under 80 words.

Approach
  1. Sort the disagreement before writing anything. A silently discarded write is a correctness claim about data; the choice between 409 and 412 is taste. Only the first justifies blocking a merge, and saying which one you are doing is most of the value of the comment.
  2. Make the claim reproducible in the comment itself with an interleaving rather than a principle: A reads version 7, B reads version 7, B commits version 8, A's predicate matches zero rows, A is told it succeeded and A's edit is gone.
  3. Offer the alternative with its cost attached: return 409 carrying the current version and the revision that won, so the client can re-read and re-apply. Note that automatic retry is not the fix, because a retry re-reads the winner's state and reapplies an intent formed against data that no longer exists.
  4. Apply an escalation rule you can state: two round trips on the thread, then a call, and the service's owner decides rather than the reviewer. A reviewer who cannot be overruled is a bottleneck with extra steps.
Follow-up
  • Where would you put the test that fails if someone reintroduces the swallowed zero rowcount?
  • The author says clients cannot handle a 409. How do you check whether that is true?
  • 01

    Tell me about a time you were given an open-ended problem and had to define its boundaries yourself.

  • 02

    Describe a moment when someone challenged your approach part-way through the work. What did you change, and what did you keep?

  • 03

    Tell me about something you shipped quickly. What did you cut, and how did you decide?

  • 04

    Describe an incident or traffic spike you helped handle. What was the first signal, how did you find the cause, and what changed afterwards?

  • 05

    Tell me about working with a product manager, operations team or mobile engineer whose priorities differed from yours.

PracHub preparation framework ↗
How hard is the Citizen (NY) technical interview?

Candidates describe it as practical and quick-moving. It is likely to feel harder if your preparation has been purely theoretical, because the reported tasks include building working code: an API design with real payloads, a dashboard, a map and a form. Practise producing a running solution, not only an outline.

Citizen (NY) Software Engineer candidate reports ↗
Which technologies should I prepare?

The role lists JavaScript or TypeScript, React and Node.js, experience with REST and real-time APIs, and database design, caching and data modelling. Geospatial data, mapping libraries such as Mapbox or Leaflet, WebSockets, Kafka or RabbitMQ, and mobile development are listed as nice-to-have, so a Leaflet map and a WebSocket or Server-Sent Events example are worth building.

Citizen (NY) Software Engineer candidate reports ↗
How should I prepare for the web application implementation questions?

Build the reported tasks from an empty folder: a filterable incident feed, a map that polls and updates markers, and a validated report form with location. Fetch data, keep state in React, handle loading and error cases, cancel stale requests, then style. Keep a scaffold you can start fast so setup does not use up your build time.

Citizen (NY) Software Engineer candidate reports ↗
How long does the process take?

Candidates report three rounds over roughly 3 to 5 weeks, starting with a Recruiter Call and a Technical Screening before the onsite interviews. Scheduling varies, so ask your recruiter for the sequence and expected timing in writing.

Citizen (NY) Software Engineer candidate reports ↗
Will there be a system design round?

Reports say recruiters may mention one, but the loop is described as emphasising practical API design and web application work. Prepare both: a spoken design of the geolocation push dispatcher, and written endpoints, payloads and status codes for the incident API. Ask the recruiter exactly what the design stage will look like.

PracHub Software Engineer practice ↗
What if the prompt is vague or the interviewer asks me to change course?

Candidates report open-ended prompts and occasional requests to simplify or switch approach. Ask about scale, inputs and edge cases first, state your assumptions, build the smallest working version, and say what you would add next. When you are asked to change direction, restate the new requirement and adapt the code you have rather than restarting.

Citizen (NY) Software Engineer candidate reports ↗
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.