Project case study
HungerStation Microservices
Trace a checkout across service boundaries
A .NET 8 food-ordering project that separates authentication, catalog, carts, orders, and background consumers using HTTP APIs and Azure Service Bus.
- C#
- .NET 8
- EF Core
- Azure Service Bus
- Stripe
The problem
A checkout combines product prices, discounts, payment state, and work that can happen afterward. Splitting these responsibilities into services makes the boundaries explicit, but also creates places where one step can succeed while another fails. This project follows those boundaries from a cart request to an order and its reward message.
How it fits together
01
Cart
Fetch products and coupons over HTTP to calculate the total.
02
Order
Save a pending order with its line items and prices.
03
Payment
Create a Stripe session and query its payment status.
04
Rewards
Publish reward data to a topic for a separate consumer.
Seven service projects sit behind an ASP.NET Core MVC frontend. AuthAPI uses ASP.NET Core Identity and signed JWTs. A separate Service Bus queue carries cart-email requests to EmailAPI, whose current implementation renders and stores the message body.
Decisions & tradeoffs
Give each service its own data model
Services define separate EF Core contexts; most use PostgreSQL, while orders and rewards use SQL Server. The cart composes product and coupon data through HTTP instead of joining their tables. This makes ownership explicit, but the cart request also depends on those services being available.
Move follow-up work onto a message bus
Cart details need immediate HTTP responses, while email requests and rewards use queues or topics. The payment-validation endpoint saves an approved order before publishing its reward message. Those are separate operations with no transactional outbox, leaving a failure window between database persistence and publication.
Keep the reward contract small
The reward message carries an order ID, user ID, and reward activity. Its consumer writes a separate reward record, keeping it independent of the order schema. Repeated payment validation or message delivery can still create duplicate records because the handler has no check that an order has already earned rewards.
Evidence & validation
The linked source traces cart composition, Stripe status validation, message publication, and reward handling. The inspected revision contains no automated test project or reproducible benchmark workload, so this case study makes no measured latency or end-to-end reliability claim.
The reward consumer requests IRewardService, but startup registers only the concrete RewardService. That registration needs correction before exercising the consumer. A local run also needs database, Stripe, and Service Bus configuration; the producer and consumers read different configuration keys.
The reward handler catches database failures without rethrowing, after which the consumer can complete the message. Useful next checks are a failed database write, duplicate delivery, and interruption between order persistence and publication. EmailAPI currently logs generated content without calling a mail transport.