5 Prisma Schema Mistakes That Will Haunt Your Android App
After teaching hundreds of developers how to pair Prisma with Jetpack Compose, I see the same schema mistakes over and over. Here's what to avoid before your app hits production.
---
1. Skipping @updatedAt on mutable models
model Task {
id String @id @default(cuid())
title String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt // ← Don't forget this
}Without @updatedAt, you have no way to sort by "recently modified" in your Compose UI — and your users will ask for it.
2. Using String instead of enum for status fields
enum TaskStatus {
TODO
IN_PROGRESS
DONE
}
model Task {
status TaskStatus @default(TODO)
}Enums give you type safety all the way from the database to your Kotlin sealed class. String fields are a runtime bug waiting to happen.
3. Missing compound unique constraints
If a user can only have one membership per project, enforce it at the database level:
model ProjectMember {
userId String
projectId String
@@unique([userId, projectId])
}Don't rely on your API layer to catch duplicates. The database should be your last line of defense.
4. Not indexing your foreign keys
model Task {
projectId String
project Project @relation(fields: [projectId], references: [id])
@@index([projectId]) // ← Your list screens will thank you
}Every LazyColumn that loads tasks by project is running a query on projectId. Without an index, that's a full table scan.
5. Forgetting onDelete: Cascade
model Task {
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
}Delete a project and orphan 500 tasks? Your Compose UI will show phantom data until the user force-refreshes. Cascade keeps your data clean.
---
These five fixes take 10 minutes and save you weeks of debugging. I cover all of this (and a lot more) in the Prisma ORM × Jetpack Compose Workshop — where we build a full-stack Task Manager app from an empty directory to a polished Compose UI.
