DEV Community

Cover image for I Built a Super-App Backend in 2 Weeks. Here's What Nobody Tells You About the Chaos.
Oge Obubu
Oge Obubu

Posted on

I Built a Super-App Backend in 2 Weeks. Here's What Nobody Tells You About the Chaos.

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,028 PHP files
  • 236 database migrations
  • 65 commits 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

Small thing. Huge impact.


What I Learned in 14 Days

  1. Migrations are forever. Make them idempotent or make them twice. I chose twice.

  2. 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.

  3. Notifications are a product. Not an afterthought. The way you notify users IS the user experience.

  4. Commission math is a philosophical problem. It's not about the numbers. It's about who gets paid, when, and how you prove it.

  5. 1,028 files is not a flex. It's a cry for help. But the system works. Every route. Every controller. Every relationship. It all connects.

  6. 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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
unitbuilds profile image
UnitBuilds

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!

Collapse
 
ogeobubu profile image
Oge Obubu

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! 🙌

Collapse
 
unitbuilds profile image
UnitBuilds

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.

Collapse
 
unitbuilds profile image
UnitBuilds

If you're curious how long it took to build, it took 2h38min for the JabuDemo 😁

Collapse
 
threerouter profile image
threerouter

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!

Collapse
 
ogeobubu profile image
Oge Obubu

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! 🙌