Day 1: "How hard can it be?"
I had 14 days. One Laravel backend. Five verticals.
- Food delivery
- Marketplace
- Pharmacy
- Laundry
- Parcel delivery
"Just connect everything and ship," I told myself.
Narrator: It was not that simple.
The Number That Keeps Me Up at Night
By Day 14, I was staring at:
-
1,028PHP files -
236database migrations -
65commits in the Git history
Sixty-five commits in fourteen days.
That's not a project. That's a hostage situation with git push.
The Commission Problem Nobody Warned You About
Here's the thing about building a multi-vendor platform: everybody wants their cut.
The vendor wants theirs. The rider wants theirs. The platform wants its cut. And somehow, all of this needs to calculate correctly, down to the kobo, across every single order type.
I spent 3 days building a commission engine that handles:
- Vendor commission percentages
- Platform commission splits
- Rider delivery fees
- Markup calculations (global AND vendor-specific)
- Null handling for every edge case that breaks at 2 AM
"What happens when both markup types are null?"
Nobody tells you about this in tutorials. You find out at 2 AM when your test user places an order, and the whole system divides by zero.
Notifications: The Invisible Monster
You know what's harder than building an order system?
Telling people about it.
I built a notification system that sends:
- Push notifications with images (because text-only is 2019)
- Real-time status updates for every order state
- Market order events:
accepted,en route,delivered,cancelled - Pharmacy order matching alerts
- Laundry dispute handling flows
Each notification has to be:
- Instant
- Contextual
- Delivered across multiple channels
- Actually useful (not spam)
I wrote 428 lines of notification logic in one week alone.
The Payment Resurrection
Users abandon carts. Payment gateways time out. Networks flicker.
So I built a payment resurrection system: when a payment fails, or times out, customers can reinitialise and try again without losing their order state.
// Market orders — recoverable
// Pharmacy orders — resumable
// Laundry orders — retryable
All recoverable. All resumable. All tested.
Because nobody's perfect. But your payment system should be.
Real-Time Order Tracking
Every order has a lifecycle:
Placed → Accepted → En Route → Delivered
But what happens when things go wrong?
- Customer disputes a laundry item
- Rider can't find the address
- Vendor runs out of stock after confirming
I built status logs for every single state change. Every transition. Every timestamp. Every reason.
Not because the client asked for it.
Because debugging without logs is just guessing with confidence.
The Feature Toggle That Saved the Day
Not everything should be live on Day 1.
So I built an ensureFeatureAvailable method that gracefully handles feature unavailability. If a feature isn't ready, users get a clean response instead of a 500 Internal Server Error.
if (!$this->featureEnabled($feature)) {
return response()->json([
'message' => 'This feature is coming soon.',
], 403);
}
Small thing. Huge impact.
What I Learned in 14 Days
Migrations are forever. Make them idempotent or make them twice. I chose twice.
Edge cases aren't edge cases. They're just cases you haven't hit yet. I handled null values in markup calculations on Day 12. Should've been Day 1.
Notifications are a product. Not an afterthought. The way you notify users IS the user experience.
Commission math is a philosophical problem. It's not about the numbers. It's about who gets paid, when, and how you prove it.
1,028files is not a flex. It's a cry for help. But the system works. Every route. Every controller. Every relationship. It all connects.Logs are not optional. If you can't trace an order from placement to delivery, you're not building a system. You're building a house of cards.
The Numbers
| Metric | Count |
|---|---|
| Days | 14 |
| Git commits | 65 |
| PHP files | 1,028 |
| Database migrations | 236 |
| Verticals shipped | 5 |
| Edge cases fixed at 2 AM | 7 |
| Cups of coffee | [redacted] |
The Architecture
├── Market Orders
├── Pharmacy Orders
├── Laundry Orders
├── Restaurant Orders
├── Parcel Delivery
├── Payment Recovery
├── Admin Dashboard
├── Spin Campaigns
├── Promo Engine
└── Notification System
One backend. Five verticals. One codebase.
What's Next
The backend is live. The API is stable. The foundation is solid.
But this is just the beginning.
Building the infrastructure was the hard part.
Making it scale? That's the interesting part.
If you're building something similar and want to talk shop, or if you just want to feel better about your own deadline, hit me up.
P.S. — If anyone asks, yes, I did rewrite the same migration three times. No, I will not elaborate.
Top comments (6)
Really cool for 2 weeks. I'm actually hitting a similar point with my V.E.L.O.C.I.T.Y. framework. Started as an infra for bank transactions, then turned into into a fast-food restaurant management system, then into a messenger app like whatsapp, a file-share system, a remote desktop system, then an IDE and finally an OS 😅 At some point should probably consolidate it all and just call it a super-app.
A note on the resurrection system, have you considered an outbox? That way you can have the transaction saved and execute until it works. Demo You can have a look at this 1, I think it should give you a pretty solid blueprint on outbox logic, so you dont drop transactions. Should also look at the offline-first architecture of it, for a super-app, responsiveness is more important than execution, as long as the app doesnt lag, or look like it broke, it can take it's time executing the user's commands. Goodluck!
Thanks for checking it out!
That’s quite an evolution with V.E.L.O.C.I.T.Y. going from bank transactions all the way to an OS is wild! 😅
Appreciate the tip on the Transactional Outbox pattern! Using an outbox / event-driven architecture is definitely top of mind for our next scaling phase, especially for decoupling payment retries and ensuring strict event consistency across all 5 verticals.
The offline-first approach is also a great point; keeping the UI responsive while background queues handle execution is huge for user trust. Appreciate you sharing the demo and insights! 🙌
Both also help with your load balancing. If your server gets hit with 100k actions at once, it needs to manage, without dropping a single 1. Offline-first and outboxing lets you do that.
If you're curious how long it took to build, it took 2h38min for the JabuDemo 😁
Truly impressive work! Building a full five-vertical super-app backend in just two weeks is incredible. Those tough edge cases and complex logic struggles every dev knows well!
Thank you! Those 2 AM edge cases definitely tested my sanity, but getting all five verticals running smoothly made it completely worth it. Appreciate the support! 🙌