Skip to main content
Tutorial

How I Use Prisma ORM in Production: Tips from Real Next.js Projects

4 min read

Debugging Prisma schema drift in a limo booking app cost 3 days of Ramadan traffic.

prismanextjstypeormdevopsjavascript

Last year, I spent three weeks debugging a production error for a luxury limo booking platform in Abu Dhabi that kept returning empty responses for valid customer reservations. It wasn’t a React bug. It wasn’t a Firebase config issue. Turned out, our Prisma schema had an enum value out of order compared to the actual database. Classic schema drift, but in a real business context — people couldn’t book their limos during Ramadan, which in the UAE is basically peak season.

That taught me some hard lessons about using Prisma in Next.js apps. Let me share the messy parts — not just the "just use TypeScript and you’re good" fluff.


Schema Design Is a Negotiation with Reality

I still remember the first time I converted a large Laravel/MySQL project to Prisma. The client—a real estate agency in Dubai—had 14 tables with weird inheritance patterns. I naively thought "Prisma Studio will handle it", then ended up hand-editing schema.prisma for 36 hours straight.

One trick I learned: put your enum values exactly in the order they appear in the database. Prisma maps numeric enums by index position when using the default configuration. We had a booking_status enum with "confirmed" as the second value in the schema, but the database stored it as 0. That tiny mismatch made Prisma return null results for half the app during Next.js API calls. Took me two days to figure out because the logs showed no errors — just... empty responses.

Since then, I run npx prisma format religiously, but also keep a raw SQL dump handy during migrations. Studio’s UI isn’t always trustworthy when you’ve got legacy databases.


Never Trust the Clock

Last summer, I built a React Native/Next.js combo app for plant deliveries in UAE — Greeny Corner, now on the App Store. We used Prisma with PlanetScale, which worked fine in dev. The problem hit after going live: their time-based auto-scaling kept failing during midnight migrations because of daylight saving differences between UAE (no DST) and PlanetScale’s servers in Oregon.

The errors were always at 12:01 AM UTC+4 — which is why no one noticed in test environments. Fixed it by setting process.env.TZ='UTC' explicitly in next.config.js and writing raw migration SQL to handle timezone transitions. Prisma’s docs don’t mention this, but when your clients are in the GCC, you can’t afford midnight outages because the database "took a nap".


Deployment Gotchas

Here’s the part where you expect a list of "5 Best Practices". Here instead are two actual deployment issues:

  1. Never run prisma migrate push and prisma db push at the same time in CI/CD. One client’s build pipeline corrupted their production DB schema because both commands tried to change the same index in parallel. Took me four hours to recover from a backup. Now we lock deployments with a simple bash script that checks for running migrations.
  1. Always test query complexity on actual UAE networks. I had a Next.js app in Riyadh returning 200ms TTFB locally, but 1.2s in production. The issue wasn’t Vercel. Turns out, the Prisma query depth was too complex for the client’s local ISP throttling DNS lookups. Solved it by denormalizing one relation and adding a simple select projection in the API route.

Why I Don’t Use Prisma Migrate in Some Projects

For Tawasul Limo’s booking engine, we switched to raw SQL migrations with Flyway because the business needed auditable DDL changes. They had a legal requirement to keep track of every schema change for government contracts — and honestly, I was scared of the "This action can’t be undone" warnings in prisma migrate.

So we created a hybrid setup:

  1. prisma generate for the TypeScript client
  2. Manual SQL scripts for migrations
  3. A cron job that diffs the schema.prisma against the DB nightly

It feels janky, but meets the client’s compliance needs without reinventing ORMs.


One Weird Trick You Won’t Find in Tutorials

The Prisma documentation shows perfect relations between models. In real clients’ data, things break. For a food delivery app in Jeddah, we had 10,000+ restaurants with inconsistent geolocation entries. Prisma’s findMany calls kept blowing up silently in pagination because of null latitude values.

Our fix? A custom type validation plugin in prisma/schema.prisma:

prisma
model Location {
  @@schema.validateLatitude('lat') // Custom validation we wrote
}

This adds runtime checks before Prisma sends the database query. Not in the docs but saved our ass twice during data migrations.


This is all to say: Prisma is great for Next.js apps until it starts quietly failing because of timezone confusion or enum drift. I use it for every project now, but I’ve had to fight through enough late-night errors to know that “production ready” often means “you get to debug the edge cases.”

If any of this sounds familiar — or if you want to share your own Prisma horror stories — say hi at sarahprofile.com/contact. I’m rebuilding another legacy PHP app into a Prisma/Next.js stack as I write this. Let’s suffer together.


S

Sarah

Senior Full-Stack Developer & PMP-Certified Project Lead — Abu Dhabi, UAE

7+ years building web applications for UAE & GCC businesses. Specialising in Laravel, Next.js, and Arabic RTL development.

Work with Sarah