<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahul Chaduvula</title>
    <description>The latest articles on DEV Community by Rahul Chaduvula (@rahul_chaduvula_a406acb5c).</description>
    <link>https://dev.to/rahul_chaduvula_a406acb5c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4023731%2F09f7bf76-1576-4f89-a736-7b655393a119.png</url>
      <title>DEV Community: Rahul Chaduvula</title>
      <link>https://dev.to/rahul_chaduvula_a406acb5c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahul_chaduvula_a406acb5c"/>
    <language>en</language>
    <item>
      <title>How I Built a Concurrency-Safe Reservation System</title>
      <dc:creator>Rahul Chaduvula</dc:creator>
      <pubDate>Fri, 10 Jul 2026 08:03:29 +0000</pubDate>
      <link>https://dev.to/rahul_chaduvula_a406acb5c/how-i-built-a-concurrency-safe-reservation-system-2eea</link>
      <guid>https://dev.to/rahul_chaduvula_a406acb5c/how-i-built-a-concurrency-safe-reservation-system-2eea</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens when 100 users try to reserve the same seat at exactly the same time?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without proper concurrency control, multiple users could end up booking the same seat—a classic race condition that every booking platform must solve.&lt;/p&gt;

&lt;p&gt;To better understand how production reservation systems handle this problem, I built a &lt;strong&gt;Concurrency-Safe Movie Reservation Backend&lt;/strong&gt; using &lt;strong&gt;FastAPI&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, and &lt;strong&gt;SQLAlchemy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Rather than focusing on frontend features, my goal was to explore the backend engineering concepts that make reservation systems reliable under concurrent traffic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;SQLAlchemy&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;JWT Authentication&lt;/li&gt;
&lt;li&gt;Role-Based Access Control (RBAC)&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  The Problem
&lt;/h1&gt;

&lt;p&gt;Imagine a blockbuster movie just opened for booking.&lt;/p&gt;

&lt;p&gt;One hundred users click &lt;strong&gt;Reserve&lt;/strong&gt; for the &lt;strong&gt;same seat&lt;/strong&gt; at almost the exact same moment.&lt;/p&gt;

&lt;p&gt;A naïve implementation usually looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check whether the seat is available.&lt;/li&gt;
&lt;li&gt;Create the reservation.&lt;/li&gt;
&lt;li&gt;Mark the seat as booked.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It seems correct until multiple requests execute simultaneously.&lt;/p&gt;

&lt;p&gt;Two requests can both read the seat as available before either has written the reservation.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;❌ Duplicate bookings.&lt;/p&gt;

&lt;p&gt;Preventing this became the primary goal of my project.&lt;/p&gt;




&lt;h1&gt;
  
  
  System Architecture
&lt;/h1&gt;

&lt;p&gt;I organized the application using a layered architecture to keep responsibilities separated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
    ↓
FastAPI Controller
    ↓
Service Layer
    ↓
Repository Layer
    ↓
PostgreSQL

          ↕
        Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer has a specific responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Controller Layer&lt;/strong&gt; handles validation, routing, and authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Layer&lt;/strong&gt; contains the business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository Layer&lt;/strong&gt; manages database operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; stores the persistent data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt; coordinates distributed locks and temporary state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping these responsibilities separate made the reservation workflow easier to reason about and test.&lt;/p&gt;




&lt;h1&gt;
  
  
  Preventing Double Booking
&lt;/h1&gt;

&lt;p&gt;Instead of relying on a single protection mechanism, I used multiple layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Redis Seat Locking
&lt;/h2&gt;

&lt;p&gt;When a user selects seats, the application first creates temporary locks in Redis.&lt;/p&gt;

&lt;p&gt;Each lock follows this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lock:showtime:{showtime_id}:{seat_label}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every lock stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User ID&lt;/li&gt;
&lt;li&gt;Lock expiration timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the reservation isn't completed before the timeout, the lock expires automatically, allowing other users to reserve those seats.&lt;/p&gt;

&lt;p&gt;This prevents multiple users from selecting the same seat simultaneously.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Atomic Multi-Seat Locking
&lt;/h2&gt;

&lt;p&gt;Booking multiple seats introduces another challenge.&lt;/p&gt;

&lt;p&gt;Suppose someone wants three seats.&lt;/p&gt;

&lt;p&gt;If the application locks them one at a time, this could happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Seat A ✅
Seat B ✅
Seat C ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the user owns only part of the requested seats.&lt;/p&gt;

&lt;p&gt;To avoid this inconsistent state, I implemented &lt;strong&gt;Redis Lua Scripts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every requested seat is locked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;none of them are.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guarantees atomic seat acquisition.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Lock Ownership Verification
&lt;/h2&gt;

&lt;p&gt;Temporary locks alone are not enough.&lt;/p&gt;

&lt;p&gt;Imagine this scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User A acquires a seat lock.&lt;/li&gt;
&lt;li&gt;The lock expires.&lt;/li&gt;
&lt;li&gt;User B acquires the same seat.&lt;/li&gt;
&lt;li&gt;User A submits an old reservation request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without verifying lock ownership, User A could incorrectly reserve a seat that now belongs to User B.&lt;/p&gt;

&lt;p&gt;Before creating a reservation, the application verifies that every requested lock still belongs to the requesting user.&lt;/p&gt;

&lt;p&gt;If ownership has changed, the reservation fails safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Database Constraints
&lt;/h2&gt;

&lt;p&gt;Redis helps coordinate concurrent requests.&lt;/p&gt;

&lt;p&gt;PostgreSQL remains the &lt;strong&gt;single source of truth&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I added unique database constraints so that duplicate seat reservations are impossible even if every application-level safeguard failed.&lt;/p&gt;

&lt;p&gt;This provides the final layer of protection against double booking.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Transactional Reservation Processing
&lt;/h2&gt;

&lt;p&gt;Creating a reservation involves several database operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating the reservation&lt;/li&gt;
&lt;li&gt;Saving reserved seats&lt;/li&gt;
&lt;li&gt;Updating related records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If one operation succeeds while another fails, the database could end up in an inconsistent state.&lt;/p&gt;

&lt;p&gt;To prevent this, reservation creation runs inside a single PostgreSQL transaction.&lt;/p&gt;

&lt;p&gt;Either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every operation succeeds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the transaction rolls back completely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guarantees consistency.&lt;/p&gt;




&lt;h1&gt;
  
  
  Idempotent Reservation Requests
&lt;/h1&gt;

&lt;p&gt;Real-world clients retry requests.&lt;/p&gt;

&lt;p&gt;Users double-click buttons.&lt;/p&gt;

&lt;p&gt;Browsers retry requests after network interruptions.&lt;/p&gt;

&lt;p&gt;Without idempotency, duplicate requests could accidentally create multiple reservations.&lt;/p&gt;

&lt;p&gt;To solve this, every reservation request includes an &lt;strong&gt;Idempotency Key&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the same request is received again, the server simply returns the original response instead of creating another reservation.&lt;/p&gt;




&lt;h1&gt;
  
  
  Background Workers
&lt;/h1&gt;

&lt;p&gt;Some tasks shouldn't happen during the request-response cycle.&lt;/p&gt;

&lt;p&gt;Background workers periodically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Release expired Redis locks&lt;/li&gt;
&lt;li&gt;Expire abandoned reservations&lt;/li&gt;
&lt;li&gt;Restore seat availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps temporary reservation state synchronized without blocking incoming requests.&lt;/p&gt;




&lt;h1&gt;
  
  
  Rate Limiting
&lt;/h1&gt;

&lt;p&gt;Reservation systems also need protection from abusive traffic.&lt;/p&gt;

&lt;p&gt;I implemented Redis-based rate limiting using atomic Redis operations.&lt;/p&gt;

&lt;p&gt;Protected endpoints include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login&lt;/li&gt;
&lt;li&gt;Registration&lt;/li&gt;
&lt;li&gt;Seat Locking&lt;/li&gt;
&lt;li&gt;Reservation Creation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents excessive requests while keeping the implementation lightweight.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stress Testing the System
&lt;/h1&gt;

&lt;p&gt;After implementing the concurrency protections, I wanted to verify that they actually worked.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Locust&lt;/strong&gt;, I simulated the following scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;100 concurrent users&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;All attempting to reserve &lt;strong&gt;the exact same seat&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;At nearly the same moment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reservation Attempts&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Successful Reservations&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed Reservations&lt;/td&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate Bookings&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Exactly one reservation succeeded.&lt;/p&gt;

&lt;p&gt;Every competing request failed safely.&lt;/p&gt;

&lt;p&gt;I also tested:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple users reserving different seats simultaneously&lt;/li&gt;
&lt;li&gt;Lock expiration and recovery&lt;/li&gt;
&lt;li&gt;Database transaction failures&lt;/li&gt;
&lt;li&gt;Redis failure scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tests gave me confidence that the reservation workflow behaves correctly under concurrent load.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Learned
&lt;/h1&gt;

&lt;p&gt;This project taught me far more than building CRUD APIs.&lt;/p&gt;

&lt;p&gt;Some of the biggest takeaways were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concurrency bugs are much harder to reproduce than normal application bugs.&lt;/li&gt;
&lt;li&gt;Redis works best as a coordination layer—not as the source of truth.&lt;/li&gt;
&lt;li&gt;Database constraints remain essential, even when distributed locking is used.&lt;/li&gt;
&lt;li&gt;Transactions are critical for maintaining consistency.&lt;/li&gt;
&lt;li&gt;Correctness under concurrent traffic is often more important than adding new features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most backend tutorials stop after implementing CRUD operations.&lt;/p&gt;

&lt;p&gt;Building a reservation system forced me to think about failure scenarios, race conditions, retries, and consistency—the kinds of problems production systems solve every day.&lt;/p&gt;




&lt;h1&gt;
  
  
  What's Next?
&lt;/h1&gt;

&lt;p&gt;There are still many improvements I'd like to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimistic locking&lt;/li&gt;
&lt;li&gt;Event-driven reservation workflows&lt;/li&gt;
&lt;li&gt;Distributed tracing&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;li&gt;Kubernetes deployment&lt;/li&gt;
&lt;li&gt;Prometheus and Grafana for observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these would make the system even closer to a production-grade reservation platform.&lt;/p&gt;




&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;📂 &lt;strong&gt;GitHub Repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Rahul-2006/Movie-Reservation-Backend" rel="noopener noreferrer"&gt;https://github.com/Rahul-2006/Movie-Reservation-Backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💼 &lt;strong&gt;LinkedIn Discussion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also shared this project on LinkedIn, where I'm collecting feedback from backend engineers on the architecture and concurrency strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://www.linkedin.com/posts/rahul-ch-434b1a250_backend-python-fastapi-ugcPost-7480908963971166208-KY2M/" rel="noopener noreferrer"&gt;https://www.linkedin.com/posts/rahul-ch-434b1a250_backend-python-fastapi-ugcPost-7480908963971166208-KY2M/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd genuinely appreciate your thoughts on the locking strategy, transaction flow, or any improvements you would suggest.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
