Learning pathsPricingChecking sign-in…
GUIDED PRACTICE

To-do Reminders

Support private tasks with editable deadlines and reminders that survive restarts without sending obsolete schedules.

Support private tasks with editable deadlines and reminders that survive restarts without sending obsolete schedules. This worked design targets SDE-1; the scale figures below are exercise assumptions, not claims about a named company's implementation.

Clarify the prompt

Ask the interviewerDecision to record
One reminder or recurring reminders?Recurrence requires timezone and daylight-saving policy.
Does completing or editing a task cancel pending delivery?Define the race at dispatch.
What lateness is acceptable?Use a measurable target rather than exact wall-clock delivery.

Requirements and scope

The core deliverable is: Support private tasks with editable deadlines and reminders that survive restarts without sending obsolete schedules. The first design implements the APIs below and the state constraints in the data model. Agree the latency, freshness, retention and failure policy before adding infrastructure. Every successful acknowledgment must have an explicit meaning: accepted intent, committed state or completed external work. These are separate milestones.

Capacity and bottleneck reasoning

Assume one million tasks with 100,000 reminders/day: 1.16/s average; allow 100/s bursts. A due_at index supports a small polling worker. State a target of 99% of accepted reminders handed to the provider within 60 seconds under normal capacity.

Keep average and peak demand separate. Add replication, indexes, retries and safety headroom to raw arithmetic before selecting capacity. Load-test the busiest ownership key and recovery traffic as well as uniform happy-path throughput.

APIs and data model

  • POST /tasks {title,dueAt,timeZone,requestKey} -> task
  • PATCH /tasks/{id} {version,dueAt,completed} -> task or 409
  • GET /tasks?cursor=... -> owner-scoped page
Contract / pseudocode
task(task_id PK, owner_id, title, completed_at, due_at, version)
reminder(reminder_id PK, task_id, task_version, due_at, state, lease_until)
delivery(operation_key UNIQUE, reminder_id, provider_status)

Authorize resource ownership at the API boundary; do not trust IDs or state supplied by a client. Bind retry identity to the caller and payload for mutating operations. Reject an incompatible replay instead of returning an unrelated stored result.

Component relationships

To-do Reminders: directed relationships and authoritative boundaries
To-do Reminders: state boundaries
Read the diagram

Follow the labeled relationship panels; they are separate directed paths, not one global timeline.

Open original
To-do Reminders: state boundaries
To-do Reminders: directed relationships and authoritative boundaries

To-do Reminders: state boundaries

Step-by-step design

1. Establish the authority

Persist task and reminder intent in one transaction. Index active reminders by due_at. Workers claim bounded batches using leases and recheck task version and completion immediately before creating delivery intent.

2. Make retries and concurrent work safe

Editing increments task version and replaces reminder intent. A queued old version becomes a no-op; deleting a task must leave enough tombstone state to reject stale queue messages.

3. Scale and recover the critical path

Use stable delivery keys and track provider uncertainty. Client-side timers may improve UX but are not the durable scheduler. Store UTC instants and the original timezone for user-facing recurrence decisions.

Worked request and concurrency example

Task T has version 3 due at 09:00. At 08:59 the owner moves it to 10:00, creating version 4. A worker already holding version 3 checks the authoritative task and skips its send. At 10:00 it sends the version-4 reminder using key T:4. If the provider accepts but the response disappears, the worker reconciles or retries with provider-supported idempotency instead of silently creating a new delivery.

Failure and recovery walkthrough

Completing a task after a provider has accepted its reminder cannot recall an already sent email. Define cancellation as best effort after the dispatch boundary and display that limitation. A worker crash before dispatch is recovered after its lease expires.

To-do Reminders: one concrete failure or state-transition sequence
To-do Reminders: concrete trace
Read the diagram

This numbered trace follows one scenario; explain the durable evidence at each transition.

Open original
To-do Reminders: concrete trace
To-do Reminders: one concrete failure or state-transition sequence

To-do Reminders: concrete trace

Deep dive: task state and delivery state have different lifetimes

For this original baseline, one owner creates tasks with optional due reminders. A reminder may be queued, suppressed, dispatch-authorized, externally unknown or accepted by a provider. Completing a task does not erase history or retract a provider effect that already happened. Start with task/reminder rows, a due index and bounded workers; a client browser timer is only a convenience.

Contract / pseudocode
 task(task_id, owner_id, due_at, version, completed_at, deleted_at)
 reminder(reminder_id, task_id, task_version, nominal_due_utc, state)
 delivery(delivery_id, reminder_id, operation_key, provider_state, evidence)
 UNIQUE(task_id, task_version, nominal_due_utc, channel) for reminder occurrence

For a one-shot task, a version change creates a replacement reminder and makes older queued versions ineligible. If recurrence is added, include each nominal UTC occurrence rather than treating every daily send as the same version-only effect. Preserve cancellation/deletion evidence for the full retry and replay horizon.

Make edits replace intent rather than mutate queued messages

At 08:59, T/v3 is due at 09:00. Its owner changes the due time to 10:00. One transaction updates T to v4 and stores the new reminder/publication intent. Old queue messages remain but their task_version no longer matches. A worker rechecks owner/resource policy, task completion/deletion and current version at the authoritative dispatch decision.

Reminder version recovery: T version 3 is queued for 09:00; owner commits version 4 due at 10:00; old worker claims version 3; authoritative eligibility rejects it; only version 4 remains eligible for the later reminder
A queued old version is data to reconcile, not authority to send.
Read the diagram

Task T version 3 is queued for 09:00 → Owner commits version 4 due at 10:00 → A worker claims the old version 3 reminder → Authoritative eligibility rejects version 3 → Version 4 remains eligible for its later due time

Open original
To-do Reminders: recovery decision
Reminder version recovery: T version 3 is queued for 09:00; owner commits version 4 due at 10:00; old worker claims version 3; authoritative eligibility rejects it; only version 4 remains eligible for the later reminder

A queued old version is data to reconcile, not authority to send.

If the user completes or deletes the task before dispatch authorization, suppress the unstarted reminder. If authorization wins first, a later completion may race with an already submitted effect. Define that boundary in the product. A best-effort last check before the network call can reduce obsolete sends, but it cannot atomically coordinate task edits with an arbitrary email provider.

Persist delivery intent before the uncertain call

BoundaryDurable factRecovery
Task/edit transaction commits; queue send failsCurrent reminder and outbox intent existRepublish the same occurrence identity
Worker crashes before dispatch authorizationNo provider call authorized by that attemptReclaim bounded work and recheck eligibility
Dispatch authorized; provider result lostOriginal provider key and unknown delivery existQuery/retry the same key under provider contract
Completion wins before dispatch claimTask terminal/current version makes old reminder ineligibleSuppress it without a provider call
Completion happens after provider acceptanceMessage may already be outside the serviceRecord best-effort cancellation boundary; do not promise recall

A new worker must resolve an authorized-but-unknown delivery rather than abandon it simply because the task changed later. The stored provider identity is needed for reconciliation and duplicate prevention. If the provider cannot deduplicate or expose status, document the remaining uncertainty and retry policy rather than claiming exactly-once delivery.

Use time semantics the owner can understand

For a one-time reminder, store the chosen UTC instant plus original display timezone as needed. For “09:00 every local day,” store a named timezone and gap/fold policy and materialize eligible occurrences. Editing the timezone can affect future occurrences; define its effective version and the fate of already authorized work. Reuse the Job Scheduler rules rather than inventing a separate DST interpretation.

Due is a target, not proof of exact start time. With a two-second scan interval, one second queued and 500 ms worker/provider work, an eligible reminder can already be several seconds late under these exercise assumptions. A five-second objective needs a stage budget, adequate capacity and an overload/misfire policy; changing polling alone cannot guarantee it.

For one million reminders uniformly due over an hour, average due rate is about 278/s. If 100,000 are due at 09:00 and safe dispatch is 1,000/s, the burst needs at least 100 seconds to submit even with no other work. Rate limits, retry pressure and provider concurrency determine the real bound. Protect ordinary task reads from bulk catch-up work.

Keep ownership and diagnostics scoped

Knowing a task ID does not authorize an edit, completion or reminder-status read. Workers use scoped job evidence and current policy. Avoid placing task titles, addresses or signed links in routine telemetry. Expose lateness, suppression reason, unknown-provider age, task-version conflicts and oldest due work using bounded metrics dimensions.

Keep soft-deletion or another durable cancellation/version record until obsolete queue messages can no longer revive work. Physical cleanup must cover derived delivery/contact data under the retention policy without removing dedupe evidence prematurely. Account deletion is not implemented by deleting one task row and hoping all providers forget it.

Reminder assessment: find the irreversible boundary

Question: T/v3 was queued before the owner moved T to v4. May v3 send because it obtained a worker lease first?

Show answer and explanation

Answer: No. A lease is scheduling ownership, not current task eligibility. The authoritative task/version/terminal-state check must reject the old unstarted occurrence.

Question: The task was completed after the provider accepted the reminder. Can the UI promise the email was recalled?

Show answer and explanation

Answer: Not from a local task update. Record the actual cancellation boundary and provider evidence; external acceptance may already make recall unavailable.

Question: A due time is represented by a local daily 09:00 rule. Is adding 24 elapsed hours always equivalent to the next local day?

Show answer and explanation

Answer: No. DST and rule changes can alter eligible UTC instants. Preserve the timezone and declared calendar policy in versioned occurrence generation.

Score one point for versioned reminder identity, edit/dispatch arbitration, external uncertainty recovery, calendar semantics and bounded lateness/tenant access. Then change one-shot reminders to recurring reminders and explain why occurrence identity and dedupe lifetime must change.

See Idempotency and the transactional outbox pattern for the publication/duplicate boundaries. The task histories and timing figures are original exercises, not provider latency guarantees.

Decisions and alternatives

DecisionTrade-off
Alternative 1Database polling is simple at this workload; time buckets and a dedicated scheduler are justified when due scans or burst dispatch become bottlenecks.
Alternative 2At-least-once work with deduplicated delivery is robust. Claiming exactly-once email without provider support hides an unavoidable uncertain-outcome window.

Operational contract

Track due-to-claim and due-to-provider latency separately, lease expiry, stale-version skips and oldest pending delivery. Protect owner-scoped reads and avoid logging task text in operational events.

Choose alert thresholds from the agreed user-facing objective. Assign an owner for stuck work and a replay/repair procedure that preserves the original business identity. Bound queue depth, concurrency and recovery throughput so an outage does not produce an uncontrolled catch-up burst.

Foundation, senior and staff depth

  • Foundation: Define versioned task and reminder occurrence identities.
  • Senior: Arbitrate edits/completion against dispatch authorization and reconcile unknown deliveries.
  • Staff: Budget bursts, calendar semantics and dedupe retention under provider limits.

Practice before revealing the answer

Spend 45 minutes: 5 clarifying scope, 7 on capacity/APIs/state, 12 on the first architecture, 15 on the concurrency and failure examples, and 6 on trade-offs and operations. Draw your own design before comparing it with this chapter.

Question: Will increasing polling frequency guarantee zero reminder delay?

Show answer and explanation

Answer: No. Polling is only one delay source; queueing, clock error and provider throttling also matter. Budget each stage, bound concurrency and expose lateness percentiles.

Verification and rollout

Enumerate edit/completion before and after dispatch authorization. Replay queue messages and resolve lost provider responses with the original operation key. Verify UTC occurrence identities, cancellation tombstones and backlog arithmetic.

Primary technical reference

Official documentation for the mechanism used in this exercise. This lesson is an original interview design, not a description of undisclosed company internals.

Before this design, review these mechanisms and identify which owns the critical state transition:

Use the Interview Playbook to adapt the depth and timing, then return to the question breakdown overview.

13:00Self-guided practice timer
The timer resets when you leave this page. Save your design separately.
Your challenge

Will increasing polling frequency guarantee zero reminder delay?

Your design draft

Clarify assumptions, explain your approach, and test the difficult cases. Save your draft, then compare it with the study notes.

Read study notes

Self-review checklist

Self-guided practice. Automated AI feedback and code execution are not connected.