Skip to main content

Command Palette

Search for a command to run...

Building a Real-Time Carpooling App with AWS

Updated
13 min read
Building a Real-Time Carpooling App with AWS
R

I'm a full-stack developer who loves to code 👩🏻‍💻 I enjoy learning new things and am always ready to face new challenges along the way. Embark on this journey with me as I write about tech issues I encounter in my day-to-day work as a developer 💻

A

I'm a passionate developer building meaningfull, scalable mobile & full-stack apps. I specialize in Flutter, Java, Python, and cloud-native technologies like AWS, CI/CD, and serverless architecture.

Big shoutout to my co-author Aneesa Shaik, who collaborated with me throughout this project and contributed to making RUCarpooling what it is!

As international students, we found daily rides via Uber or Lyft unsustainable, and public transport wasn’t always reliable. We realized many students with cars were open to offering rides, but there was no easy way to connect.

That gap sparked the idea for RU Carpooling: a student-first, community-driven ride-sharing app designed to make commuting more affordable, convenient, and sustainable. Our goal was not only to reduce transportation costs and carbon emissions but also to build a scalable, serverless solution using AWS that could dynamically match rides in real time, support student authentication, and deliver a smooth user experience across devices.

What it does

RU Carpooling connects Rutgers students to share rides, split expenses, and reduce their environmental impact. The platform matches riders with nearby drivers based on factors like route, timing, and seat availability. Riders can filter listings by trunk space, pet-friendliness, or wheelchair access.

To ensure campus safety, all users are authenticated via Amazon Cognito, confirming valid NetIDs. Built-in notifications keep both drivers and riders informed of confirmations, updates, or cancellations in real time.

We also prioritized sustainability and accessibility. Using Groq APIs, the app supports speech-to-text for hands-free location input and estimates the carbon emissions saved per ride, delivering fun summaries that show users the impact they’re making, one shared ride at a time.

Tech Stack

A Serverless AWS architecture designed for scalability, affordability, and real-time performance.

  • Frontend: Developed with Flutter and Dart to ensure a smooth, cross-platform experience on both Android and iOS.

  • Backend: Powered by Python (FastAPI) with Boto3, we integrated deeply with AWS services including:

    • AWS Lambda for serverless compute

    • API Gateway for managing RESTful APIs

    • Step Functions for orchestrating complex workflows like ride confirmations

    • EventBridge for decoupled, event-driven triggers

    • CloudWatch for monitoring and logging

    • WebSockets for real-time updates

  • Authentication: User sign-up and login flows are secured using Amazon Cognito, which verifies valid Rutgers NetIDs and provides role-based access control.

  • Database: We use Amazon DynamoDB for fast, highly available, and cost effective NoSQL data storage, ideal for student profiles, ride listings, and chat metadata.

  • Groq AI: We incorporated Groq APIs to deliver:

    • Speech-to-text location input for accessibility

    • Carbon emission calculations and summaries to promote sustainability and awareness

Why We Chose AWS

From the start, RU Carpooling needed to be scalable, secure, and fast to build, not just for production use, but under hackathon timelines. We evaluated multiple backend options, including Firebase for real-time data and Auth0 for authentication. But coordinating across multiple providers created unnecessary overhead and limited extensibility.

AWS offered a unified, serverless ecosystem that allowed us to move fast without compromising on architecture quality. With native integrations across identity, compute, storage, and observability, we could build a real-time, event-driven platform without gluing together third-party tools.

The benefits were immediate:

  • Faster development through service cohesion and Boto3 SDKs

  • Scalable performance without managing infrastructure

  • Granular IAM policies for tight security around student data

  • EventBridge + Lambda orchestration for modular, decoupled workflows

  • Cloud-native observability with CloudWatch for logs and alerts

By choosing AWS, we reduced architectural complexity, avoided vendor lock-in, and built a production-grade platform that could scale from a hackathon prototype to a campus-wide utility.

Serverless Architecture

🔐 API Gateway & Cognito: Entry Point + Secure Access

All client interactions, like posting a ride or browsing available seats, begin at Amazon API Gateway, which acts as our centralized, secured entry point. With usage plans and authorization policies in place, we ensure that only authenticated Rutgers students can access protected endpoints.

Authentication is handled via Amazon Cognito, which manages sign-up, login, and token issuance based on NetID validation. This offloads the complexity of identity workflows while maintaining enterprise-grade security.

⚙️ Lambda Functions: Stateless Business Logic

Our application logic runs in modular AWS Lambda functions, each handling a specific task, ride creation, matching logic, cancellation, etc. This granular function design enables isolated updates, simplified testing, and independent scaling. Lambda’s auto-scaling model gracefully handles traffic spikes, especially during high-demand events like class cancellations.

Architecture Of RUCarpooling

🗂️ DynamoDB + Geo-hashing: Fast, Flexible Data

We use Amazon DynamoDB as our primary datastore to persist ride listings, user profiles, and location metadata. Geospatial lookups are optimized using geohash-based indexing, enabling low-latency filtering by location. DynamoDB’s on-demand capacity mode ensures automatic scaling and cost efficiency, paying only for what we use.

📣 EventBridge: Decoupled Event Processing

To maintain modularity, we rely on Amazon EventBridge to orchestrate internal workflows. When a new ride is posted or updated, EventBridge publishes an event that triggers downstream processes like notification dispatch, index refreshes, or ride suggestions, enabling reactive logic without tight coupling.

🧭 Ride Matching Algorithm & Geospatial Intelligence

With thousands of students traveling, our goal was to ensure real-time search at scale without compromising accuracy or speed. To achieve this, we designed a geo-aware, serverless matching engine using OSRM, geo-hash compression, and custom similarity scoring.

🚘 OSRM-Based Route Processing at Ingestion Time

In earlier iterations of the app, route generation via the Open Source Routing Machine (OSRM) was handled during the ride search flow, meaning each rider request triggered a new route computation. While this worked for small datasets, it introduced unnecessary latency and added pressure to Lambda runtime limits.

To improve performance, we shifted OSRM route generation to the ride posting phase. When a driver creates a listing, we immediately call OSRM to:

  • Generate the full driving route between origin and destination

  • Return the estimated travel time and distance

  • Produce a dense set of route waypoints (geometry.coordinates)

We then reduce this route into a compressed geohash sequence, a set of compact strings that represent sections of the earth’s surface. The step size used for compression is dynamically adjusted based on the route length: shorter routes are sampled densely, while longer ones are sampled more sparsely. This ensures geospatial accuracy without bloating storage.

The resulting geohash set is stored in Amazon DynamoDB, along with the route metadata and ride-level attributes such as driver name, seats, and accessibility options.

By precomputing and persisting route intelligence during ride creation, we eliminated real-time OSRM dependency from the search workflow entirely, dramatically improving response times and reducing redundant external API calls.

🔍 Geospatial Filtering with DynamoDB and Geohash Indexing

During a ride search, the rider's own start and end locations are passed to OSRM just once to generate their planned route. This route is then converted to geohashes using the same sampling technique as the driver’s.

To find viable matches, we query DynamoDB for rides that:

  • Occur within a ±2-hour time window

  • Have at least the requested number of available seats

  • Match optional constraints (e.g., pet-friendliness, trunk space)

Crucially, we do not scan the entire table. Instead, we apply a geo-hash prefix–based filtering strategy. Using either a Global Secondary Index (GSI) or a thoughtfully designed partition key, we map rides to approximate location buckets, e.g., all rides whose starting geo-hash begins with "dr5r" (New Brunswick area) for the day "2025-04-14".

This allows us to use .query() instead of .scan() in DynamoDB, cutting down read latency, improving throughput, and dramatically reducing cost under high load.

📊 Real-Time Similarity Scoring (Now in Parallel)

After retrieving a candidate set of rides, we need to rank them based on relevance. We use a composite scoring function that accounts for:

  • Geo-hash similarity between rider and driver routes (Jaccard overlap)

  • Time difference between preferred and posted departure times

  • Seat availability ratio (seats left vs. total capacity)

To reduce latency as the number of rides scales, we now parallelize the computation using Python’s concurrent.futures module. This change allows the Lambda to fan out scoring tasks across threads internally, dramatically reducing the time it takes to score large result sets and keeping response latency well within real-time bounds, even with dozens of candidate rides.

This flow will soon be orchestrated through AWS Step Functions to enable even better fault tolerance, retries, and parallelism at scale.

📦 Geo-hash Optimization for Storage and Lookup Efficiency

Geo-hash data can become quite verbose, especially for long distance routes. To keep our storage efficient and matching fast, we adopted two key strategies:

  1. Dynamic Sampling: Step size during geo-hash encoding is adjusted based on route length, ensuring we don’t over-represent long trips.

  2. Prefix Compression: We store only unique geo-hash prefixes, stripping away redundant coordinates that would otherwise inflate DynamoDB item size.

This not only reduced the size of stored route data but also improved comparison performance during similarity scoring, since fewer set operations are needed, and memory usage is lower during Lambda execution.

Notifications Architecture

One of the defining features is its ability to keep users in the loop, instantly. Whether it’s a new ride being posted, a seat getting booked, or a last-minute cancellation, timely communication is essential. With students constantly on the move, we needed a notification system that was fast, scalable, and required minimal operational maintenance. AWS made that possible.

At the core of our design is Amazon EventBridge, which acts as the event backbone of the entire system. Rather than having individual functions directly notify users, we take a clean, decoupled approach: when a key action occurs, such as a ride creation, booking request, or ride cancellation, a dedicated Lambda function emits a structured event into EventBridge. This event carries all the necessary context: who triggered the action, which ride it refers to, what kind of update occurred, and who might need to hear about it.

From there, EventBridge rules handle the routing. Each event type is directed to the appropriate downstream process. For example, a BookingRequested event is routed to a Lambda function responsible for alerting the driver, while a RideCancelled event might notify every student who had booked a seat. This separation between event producers and consumers gives us the flexibility to evolve notification behavior independently from core business logic. If we later choose to notify ride followers or suggest alternative matches when a ride is canceled, it’s as simple as subscribing another consumer to the same event, no rewrites needed.

Delivery happens through Amazon API Gateway's WebSocket support, which we use to maintain real-time connections with client apps. This allows us to push updates to the frontend immediately, without requiring students to refresh their screens or poll the server. During testing, this design proved especially valuable, notifications of seat count changes or schedule shifts propagated instantly, even under concurrent load.

What makes this architecture particularly future-proof is how easily it extends. While we currently prioritize real-time in-app updates via WebSockets, the same events could just as easily be routed to Amazon SNS for SMS delivery or Amazon SES for email confirmations. EventBridge’s flexible rule based system lets us wire up new channels with minimal effort, without affecting the existing user experience.

Step Functions: Orchestrating Multi-Step Logic Without Overhead

Behind the scenes, we validate input, generate a route, find nearby students, send real-time notifications, and log the activity for analysis. While these tasks are logically connected, each one involves different systems, failure conditions, and performance considerations.

Initially, we handled this chain of actions inside a single Lambda. It worked, but as the system grew, the complexity became hard to manage. Debugging issues meant digging through logs from multiple branches of logic. Scaling individual steps wasn’t possible. And any failure mid-way meant rerunning the entire process. We needed something better.

We turned to AWS Step Functions, a serverless orchestration service that allowed us to coordinate each part of the ride-posting workflow as an independent, modular step. Each Lambda now handles one responsibility: validating input, storing the ride, identifying geohash segments, matching users, and notifying them through WebSockets. The logic flows as a state machine, and each transition is visible, retryable, and self-contained.

With Step Functions, a failure in one geohash lookup doesn’t bring down the whole process. Notifications only fire once all inputs are confirmed. And with visual execution traces and native logging, we can trace every ride from creation to confirmation—without writing our own coordination logic.

Since Step Functions are billed per state transition, and all our compute is handled by short-running Lambdas, the entire workflow remains lightweight. We avoid idle servers, unnecessary retries, and pre-allocated infrastructure—all while running an event-driven pipeline that can handle bursts at scale.

In short, Step Functions gave us the confidence to treat ride publishing as a first-class workflow, not just a backend script. It brought clarity, scalability, and future flexibility to a process that’s core to the app’s experience. And it’s a pattern we’ll lean on again as the platform grows.

Measurable Benefits and KPIs

While RU Carpooling began as a passion project, driven by real student needs and built under hackathon constraints, it’s already showing signs of production-grade performance and architectural efficiency.

In small-scale test deployments with a closed group of classmates, ride searches consistently returned in under a second. That performance is directly enabled by our serverless foundation: AWS Lambda executes logic without startup lag, and Amazon DynamoDB delivers low-latency, key-based queries, ideal for geohash lookups. Even as we simulated heavier usage, the system handled burst traffic gracefully, hinting at the scalability we’d need if rolled out campus-wide.

RU Carpooling runs entirely on a pay-per-use model. Each Lambda function, DynamoDB read, WebSocket message, and event bus trigger is billed only when used. During development and testing, this translated to nearly negligible monthly spend, something especially meaningful for student builders with limited resources. It allowed us to experiment freely, iterate quickly, and focus on product thinking without being constrained by backend provisioning or cost overhead.

Performance Benchmarks
| Metric | Result |
|--------|--------|
| Search Latency (p95) | < 1s |
| Ride Matching Fanout | Parallelized via concurrent.futures |
| Cold Start Issues | Avoided via modular Lambdas |
| Monthly Cost (Testing Phase) | <$1 |

Beyond raw performance, the architecture itself accelerates innovation. Features like ride notifications, built on Amazon EventBridge, triggered instantly and reliably in test runs, delivering real-time updates without writing custom pub/sub logic. Step Functions ensured that even multi-step workflows like ride posting and user matching stayed resilient and observable, with retries and fan-out logic handled natively.

Although we haven’t yet opened RU Carpooling to the broader student population, the early KPIs are clear: this is a system that’s fast, cost-effective, and built to grow. Its serverless foundation gives us not just performance, but freedom to scale up, extend functionality, or plug in future enhancements like payment workflows, AI-based route suggestions, or trust-based driver validation, all without rewriting core infrastructure.

For us, that’s the real win. RU Carpooling proves that even with limited resources, student developers can build systems that are technically polished, highly efficient, and designed to scale, thanks to the power and flexibility of AWS.

Conclusion

RU Carpooling began as a personal project rooted in a real student need, but thanks to AWS, it’s evolved into a scalable, event-driven platform that performs like a production system.

Even at a small scale, the results have been promising. Tests with simulated users consistently delivered fast search results, reliable event triggers, and near-zero operational costs. This gives us confidence not only in the technical foundation we’ve built, but in its potential to serve the broader student body should we take the platform live.

Ultimately, RU Carpooling demonstrates what’s possible when powerful cloud primitives meet practical problems. With AWS as our foundation, we’ve proven that a small team can deliver performance, scalability, and user experience at a level once reserved for well-funded startups. And we’re just getting started.

📚 References & Resources

Key AWS resources that shaped RU Carpooling:

These helped us move fast, stay lean, and build with confidence.


The AWS Buildbook

Part 1 of 1

The AWS Buildbook is a collection of real-world projects I’ve designed, built, and shipped using AWS. No fluff. Just the lessons we’ve picked up through late nights, broken deploys, and the occasional small win that kept me going.