Personal project · staging

ReturnRider

A return-and-refund tracker that reads commerce emails, computes return deadlines, and vaults wallet passes — built as a polyglot monorepo to keep the slow work off the request path.

NestJS 10 · Prisma · PostgreSQL 16 · Redis · BullMQ · Expo / React Native · Go 1.22 · Terraform (AWS VPC · RDS · ElastiCache · S3) · Swagger/OpenAPI

What it is

ReturnRider ingests commerce signals from a user's inbox, works out when each purchase's return window closes, tracks the shipment, watches for the bank refund, and stores the QR pass in Apple or Google Wallet. It is a personal project I built to practice a real multi-service system end to end — the interesting part is the shape, not a launch.

The problem

Reading and parsing inboxes is slow, bursty, and I/O-heavy — exactly the kind of work you never want on an API's request path. It also touches the most sensitive data a user has, so email access needs a hard boundary, and any single ingestion path (an OAuth grant, an uploaded receipt) will sometimes fail. The design question is how to absorb all of that without blocking the user or the API.

What I built

Architecture

Expo / React Native app

NestJS API

Prisma · DTO validation · OpenAPI

PostgreSQL

orders · returns · refunds

Redis · BullMQ

ingestion + parse jobs

Go email-sync worker

Gmail pull + parse, off the API

External

Gmail · Plaid · EasyPost · Wallet

Two decisions and their tradeoffs

A separate Go worker for email sync, not the Node API

Inbox pulling and parsing is long-running and CPU/I-O heavy, so it lives in its own Go service that consumes jobs from Redis rather than running inside the request-handling API. The cost is a polyglot codebase — two runtimes, two deploys. The gain is that parsing can crash, retry, and scale on its own without ever touching the API's latency or event loop.

Email is primary, but never the only way in

Auto-discovery from a connected inbox is the best experience, but gmail.readonly is a broad, sensitive grant that a user can decline or that can fail in production. So manual add and receipt scan are first-class backup paths, and the product rule is that email data is never sold. The tradeoff is more entry code paths to build and keep correct — worth it so a missing OAuth grant never leaves a user stuck.

Status

Open to new-grad roles

ResumeEmail