Reserve rooms and handle recurring local times
Application background
An employee chooses a room and meeting time in an office calendar. The application shows availability, then saves the reservation. The displayed result can become old before the employee clicks Confirm because another organizer may reserve the room first.
Time zones add another problem. A meeting repeated at 09:00 London time should follow London's clock when daylight-saving time changes, even though its UTC time may change.
Example walkthrough
01 · Try this input
- Input / starting state
- Ana requests room 4 from 09:00 to 10:00
- Expected result
- Save the reservation if no conflicting booking exists.
02 · Try this input
- Input / starting state
- Ben requests room 4 from 09:30 to 10:30
- Expected result
- Reject the overlap and ask him to choose another slot.
03 · Try this input
- Input / starting state
- A weekly London meeting crosses a clock change
- Expected result
- Keep the declared local-time rule.
The final reservation operation must check and save together. A previous availability search is useful information, but it cannot guarantee the room is still free.
Your assignment
Deliver: Build room search and reservation operations that cannot accept overlapping bookings. Define and demonstrate how recurring meetings behave across clock changes.
Required behavior: POST /rooms/{id}/bookings accepts an interval and request ID. Conflicting room occupancy returns 409. GET /availability is advisory. The booking transaction decides whether the interval is still available.
The required first milestone is a working local implementation of the behavior above. The numbered implementation steps define the scope. The cloud architecture is a later extension, not something the starter has already provisioned.
Get the code and run the supplied example
The code is in the public junior-to-staff repository. Install Git and Python 3.12+. No AWS account or Python packages are required for this first run. If you already have a checkout, use it and skip cloning.
git clone https://github.com/Soulful-Iris/junior-to-staff.git
cd junior-to-staff
python3 examples/architecture-starts/calendar_availability.py
Supplied file: examples/architecture-starts/calendar_availability.py. You can also read or download the source here (download file, source below).
Read the supplied code · calendar_availability.py
"""Local mechanism demonstration for calendar-availability. No AWS resources are created."""
bookings=[]
def reserve(start,end):
if end<=start: return '400 invalid interval'
if any(start<b and a<end for a,b in bookings): return '409 room occupied'
bookings.append((start,end)); return '201 reserved'
for interval in [(600,660),(630,690),(660,720)]:
print(interval,reserve(*interval))
print('Minutes from midnight:',bookings)
This program is a mechanism demonstration: it runs the small scenario in one process and prints the result. It is not an HTTP service, a complete application, or an AWS deployment. A successful run demonstrates this mechanism only. It does not establish the workload or failure guarantees of the application you will build.
Example output from the supplied run:
Generated IDs and timestamps may differ. Compare the state transitions and outcomes.
(600, 660) 201 reserved
(630, 690) 409 room occupied
(660, 720) 201 reserved
Minutes from midnight: [(600, 660), (660, 720)]
Set up your implementation workspace
Create work/calendar-availability/ in your checkout (or use a separate repository). Copy the supplied mechanism into that directory as mechanism.py, then extract its state transitions into functions you can call from your implementation. The record and module names below describe what you must implement. They are not a promise that files with those names already exist. Keep a README.md beside your implementation with its exact run commands and observed results.
Local components and state to implement
This table names the records, interfaces or decision inputs for your deliverable. Unless a name is explicitly linked to supplied source above, it is something you create. Implement the local state transitions first, then connect the HTTP, storage or worker boundaries required by the steps.
| Record / module | Key or interface | Responsibility |
|---|---|---|
| bookings | room_id,booking_id,start_utc,end_utc | Committed occupancy. Enforce no overlap at the database. |
| series | series_id,local_time,IANA_zone,rule,revision | Recurrence intent plus exception dates. |
| booking_operations | organizer,request_id,payload_hash | Exact retries reuse one booking. |
Implement the assignment
1. Implement one room first
Store UTC instants and require end after start. In PostgreSQL, use a GiST exclusion constraint combining room equality with overlapping tstzrange values. Enable btree_gist where required. A SELECT availability followed by an unconstrained INSERT can double-book under concurrency.
2. Add recurrence without losing local intent
Keep the IANA timezone, local recurrence rule and occurrence exceptions. For this exercise skip nonexistent local times and choose the earlier instant for ambiguous times. Display that policy. Recompute future materialized occurrences after rule edits under a series revision.
3. Separate browsing from committing
Cache availability briefly with an as-of timestamp. On submit, recheck through the authoritative constraint. Preserve the organizer’s proposed time when returning a conflict, and offer a fresh availability read.
4. Handle series edits and cancellation
Change only the explicitly chosen occurrence or future series segment. Use stable occurrence IDs and transactionally update occupancy. Notify attendees asynchronously from an outbox. A failed email must not roll back an already reserved room.
Demonstrate the completed local result
01 · Try this input
- Input / starting state
- Run the starting program
- Expected result
- The overlap at 10:30 conflicts. The back-to-back 11:00 booking succeeds.
02 · Try this input
- Input / starting state
- Submit two overlapping reservations concurrently
- Expected result
- One commits and the other returns a conflict from the authoritative write.
03 · Try this input
- Input / starting state
- Cross a daylight-saving transition
- Expected result
- The recurring event follows the published local-time policy.
Handoff: In your implementation README, include the start command, one successful operation, the failure case above and the resulting stored state or decision. State which dependencies are simulated. Someone with a fresh checkout should be able to reproduce this without your chat history.
Workload assumptions and capacity decisions
These are constructed exercise assumptions. The stated workload is a design target. The local demonstration does not establish that throughput. Use the estimation constants to check units before choosing capacity.
| Input or objective | Calculation / consequence |
|---|---|
| 100 million calendars. 3 million active/day | 3% daily activity. Partitioning every request by calendar avoids global scans. |
| 100 bookings/s exercise peak. 60-day availability view | Expand bounded recurrence horizons. Do not materialize an infinite series. |
| Intervals are [start,end) | A 10:00–11:00 booking and an 11:00–12:00 booking do not overlap. |
Map the local implementation to AWS
Deployment status: local only. Running the supplied command creates no AWS resources and configures no cloud connections. The diagram is a proposed deployment of the completed application. Each box needs either a deployed runtime, a provisioned service or an explicitly external dependency.
Read the diagram by following the arrows from the entry point: application code accepts the request or event, the state owner commits it, and any worker produces the later result. The table ties those roles to code and adapter work. Multiple boxes do not imply multiple Python files already exist.
A relational occupancy constraint fits interval exclusion directly. DynamoDB conditional puts alone do not prevent arbitrary overlapping intervals without an additional serialized room-calendar design.
| Local responsibility | Cloud destination and role | Implementation still required |
|---|---|---|
| Local HTTP boundary or the endpoint you will add | Amazon API Gateway: booking API | Create routes and an integration. Translate requests and responses and configure identity validation. |
| Python operation or worker function | AWS Lambda: booking application | Write a Lambda event adapter, package its dependencies and give its role only the required resource actions. |
| Local records and transaction boundary | Amazon Aurora PostgreSQL: occupancy authority | Write PostgreSQL schema/migrations and a database adapter. Configure credentials, connection limits and recovery. |
| Local pending-work collection | Amazon SQS: notification queue | Publish committed job intent, consume messages and persist deduplication/ownership state. Add visibility, retry and dead-letter handling. |
| Python operation or worker function | AWS Lambda: notification worker | Write a Lambda event adapter, package its dependencies and give its role only the required resource actions. |
| Local notification delivery fixture | Amazon SES: email transport | Implement email submission and provider outcome tracking with verified sender configuration and scoped credentials. |
Provision resources, then connect the application
| Resource or boundary | Initial configuration and reason |
|---|---|
| Aurora PostgreSQL | Use a supported engine and range/exclusion constraint. Cap pooled connections and keep reservation transactions short. |
| Application configuration | Store timezone identifiers, not fixed UTC offsets. Pin and deliberately update timezone data used for expansion. |
| Notification queue | Bound retries, record delivery state and keep room occupancy independent of provider health. |
Use one disposable AWS environment for the cloud exercise. Put the named resources in infra/template.yaml or your existing IaC tool, pass resource IDs through configuration, and scope each runtime role to its own tables, buckets and queues. The diagram is a design to implement. It is not a claim that these resources have been deployed. Record the commands you used to deploy and remove the exercise resources.
For concrete provisioning commands, configuration wiring and cleanup, use the AWS foundation guide. It includes a deployable table/queue/object-storage foundation and explains which application and service adapters you still implement.
A provisioned queue or table does not make the local program use it. Configure resource IDs in the deployed runtime, replace the local adapter, and replay the same successful and failing operation against that runtime. Record the deployed commit and observable result, then remove the disposable resources using your infrastructure tool.
Extend the design after the baseline works
Worked follow-up: Reserve three rooms as one booking
The organizer should not receive a successful meeting with only two rooms. Independent availability checks are stale as soon as another organizer reserves a room.
| Starting design | Changed requirement |
|---|---|
| A booking checks one room for an overlapping interval. | One meeting must acquire all three requested rooms or none. |
Revised architecture. Follow the changed responsibility and failure path below. This is a design to implement. The supplied local example does not provision these components.
What to implement. For rooms in one relational store, acquire room locks in a stable ID order and enforce interval exclusion inside one transaction. Insert the meeting and all reservations together. Roll back the entire transaction if any room conflicts. Use an outbox for invitations after the booking is saved. If rooms belong to independent providers, use expiring holds and a visible pending booking, then compensate partial holds. That alternative has a different user contract.
Walk through the result. Request R1, R2 and R3 for 09:00–10:00 while R2 is already occupied. The result is a conflict and no new reservation for R1 or R3. Compare that with the external-provider variant, where the user sees pending until all holds are confirmed. Hand over both the transaction boundary and cancellation behavior.
Add a meeting requiring three rooms atomically. Compare a database transaction spanning all room constraints with independent reservations and compensation. Explain what the organizer sees if only two rooms can be acquired.
Additional design cases, alternatives and original source notes
This is a commonly listed system-design interview prompt with a concrete practice contract. Assume 100 million calendars, 3 million active users, and free/busy reads much more frequent than event writes. Clarify service guarantees and a first version before filling the board with services.
01 · Try this input
- Input / starting state
- Overlap
- Expected result
- Reject or offer another slot under one conflict rule.
Input / condition: Room booked 09:00–10:00. Request 09:30–10:30
02 · Try this input
- Input / starting state
- DST boundary
- Expected result
- Preserve local wall time with explicit zone and recurrence semantics.
Input / condition: Recurring 09:00 local meeting crosses clock change
03 · Try this input
- Input / starting state
- Concurrent booking
- Expected result
- One transaction/constraint wins. Loser sees conflict.
Input / condition: Two users claim the last room
04 · Try this input
- Input / starting state
- Invite response
- Expected result
- Reject stale event version or mark response to canceled event.
Input / condition: Guest accepts after organizer cancels
Think from the contract to the boxes
Store each occurrence as UTC instants, but retain the recurring series' local wall-time anchor, IANA zone, recurrence rule, version and exceptions. Expand future occurrences in that zone, not by repeatedly adding 24 hours in UTC. This exercise skips nonexistent spring-forward times and chooses the earlier offset for ambiguous fall-back times. Expose that policy to the organizer. Use interval overlap semantics [start,end) so adjacent meetings do not conflict. A precomputed free/busy view accelerates reads, but booking must check authoritative intervals at commit. Make invitations versioned events. A delayed response cannot resurrect a canceled meeting.
One room, one conflict authority
POST /rooms/{room}/bookings includes an idempotency key, start and end. Identity and room permission are server-checked. The PostgreSQL authority commits booking, replay result and outbox together. For a disposable PostgreSQL database, the core constraint is:
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE TABLE room_booking (
booking_id text PRIMARY KEY, room_id text NOT NULL,
starts_at timestamptz NOT NULL, ends_at timestamptz NOT NULL,
cancelled boolean NOT NULL DEFAULT false,
CHECK (starts_at < ends_at),
EXCLUDE USING gist (room_id WITH =,
tstzrange(starts_at, ends_at, '[)') WITH &&)
WHERE (NOT cancelled)
);
Concurrent overlaps conflict at this constraint. A preceding availability SELECT is only a hint. Cancel/update uses a version condition in the same authority. Event changes and outbox rows commit together. The relay sends to EventBridge/SQS and consumers deduplicate (event_id, version). EventBridge routes events—it cannot make a separate database write and publish atomic.
01 · Try this input
- Input / starting state
- Insert 09:00–10:00 and 09:30–10:30 concurrently
- Expected result
- Only one active booking commits.
02 · Try this input
- Input / starting state
- Insert 09:00–10:00 and 10:00–11:00
- Expected result
- Both commit: half-open intervals are adjacent.
03 · Try this input
- Input / starting state
- Cancellation races with a new booking
- Expected result
- Outcome follows commit order. No overlapping active pair.
04 · Try this input
- Input / starting state
- Replica still shows an old free slot
- Expected result
- Final write rechecks the primary constraint. Strict free/busy reads use the primary.
05 · Try this input
- Input / starting state
- Crash after database commit, before event send
- Expected result
- Outbox relay resumes. No missing accepted event, duplicates tolerated.
06 · Try this input
- Input / starting state
- A 09:00 recurring meeting crosses DST
- Expected result
- It remains 09:00 local under the declared expansion policy.
This is a schema and test schedule to execute, not evidence that PostgreSQL or AWS was deployed.
First diagram: Draw event authority, free/busy projection, notification delivery, and a conflict check using the exact interval boundary.
| AWS service / general role | Why it fits this design | Alternative and when it fits better |
|---|---|---|
| Amazon API Gateway / calendar API entry | Authenticate calendar reads and writes. | ALB + ECS for long-lived sync clients. |
| Amazon Aurora PostgreSQL / event + room store | Range constraints/transactions prevent conflicting reservations. | DynamoDB with one fenced per-room decision owner, or a fixed-slot model that transactionally claims every slot. Arbitrary overlap is not a conditional item check. |
| Amazon ElastiCache / free/busy cache | Speed repeated availability reads. | Read replicas for explicitly stale views. Primary or a verified watermark for strict reads. |
| Amazon EventBridge / change event router | Route changes delivered by the database outbox relay. | Outbox relay → SQS when a queue is enough. Routing and atomic publication are different jobs. |
| Amazon SQS / notification queue | Retry mail/push without blocking calendar writes. | EventBridge Scheduler for delayed reminders. |
Service choice follows the contract: the box label gives the generic job, while the table explains the AWS product and a reasonable substitute. Name which component owns durable truth, where retries happen, and the guarantee each managed service does not provide by itself.
Pressure-test the design
Follow-up: Adjacent intervals are legal. Overlapping half-open intervals conflict. Compare 09:00–10:00 against 10:00–11:00 and 09:59–10:30.
A calendar write succeeds but an invitation email is delayed. Explain source of truth, outbox, notification dedupe, and what the guest sees before delivery.
Support federated calendars across providers with different recurrence semantics. Set compatibility contracts, conflict ownership and a safe migration for stored time zones.
Practice artifact: Draw event authority, free/busy projection, notification delivery, and a conflict check using the exact interval boundary. Then trace every row in the table, draw one failure, and state what the customer observes. Suggested rehearsal: 35 minutes design, 10 minutes to challenge the guarantees.
Evidence and origin: The current community interview-question catalog lists calendar/free-busy reports at Microsoft, Oracle and LinkedIn. Individual interview dates are not provided. The entry does not show the interview date and is not a verified company rubric. The prompt contract, workload, outcomes, diagrams and solution here are original practice material. Treat company tags as reported sightings, not a prediction of your interview loop.
Interview report listing: Open the community question entry.