There’s a point where e-commerce stops being the right tool. Selling a product is a transaction. Booking a vet appointment, tracking a vaccination, scheduling a surgery - that’s a service, with state, scheduling, and records. A storefront can’t model that cleanly.
That’s why PetsFirst Health went custom: Next.js, Node.js/Express, and MongoDB, with a Flutter app on top.
I could have bolted appointment logic onto a store. I’ve seen people do it. It always ends the same way - fighting the platform, hacking around its assumptions, and shipping something fragile. When the domain is genuinely different from commerce, build for the domain.
The most important architectural decision was keeping a single Node.js/Express + MongoDB backend that serves both the Next.js web platform and the Flutter mobile app.
The temptation is always to special-case the mobile app - a slightly different endpoint here, some logic in the client there. Resist it. One clean API, consumed by both, means a feature ships once and shows up everywhere. Duplicated logic across web and mobile is how platforms rot.
Healthcare data here is document-shaped - a pet, its records, its appointments, its history. MongoDB lets that nest naturally without forcing it into rigid joins. The flexibility paid off as the services (checkups, vaccinations, surgery) each grew their own fields.
The platform runs on AWS through a GitHub CI/CD pipeline. Automated builds and deploys mean iterating on the web app and the API without manual release steps - important when a mobile app depends on that same backend staying stable.
Use the hosted platform for what it’s great at - commerce. The moment you’re modelling a real service with scheduling and records, a custom Next.js + MongoDB stack will repay the extra effort many times over.