Choosing the Right Laravel Method Actually Matters
create() vs updateOrCreate() vs upsert()
These three look similar, but using the wrong one can:
- slow your app down
- break business logic
- or silently hurt scalability
Here’s the mental model I use:
1. create()
What it does:
Always inserts a new row.
Key points
- ❌ No checking
- ❌ No updating
- ✅ Simple insert
- ✅ Triggers model events (creating, created)
- ✅ Respects $fillable
Use it when
- You know the record doesn’t exist
- You want model events, observers, timestamps, casts
2. updateOrCreate()
What it does:
Looks for a record → updates if found, creates if not.
How it works internally
- SELECT ... WHERE email = ?
- If found → UPDATE
- If not → INSERT
Requirements
- You must provide a unique or near-unique condition
- Works row-by-row
Key points
- ✅ Triggers model events
- ✅ Uses Eloquent (casts, observers, timestamps)
- ❌ Slower for bulk data
- ❌ Not atomic (race condition possible without DB constraints)
Use it when
- Single record logic (settings, profiles, configs)
- You need observers/events
- You’re working with user-driven data
3. upsert()
What it does:
Bulk insert or update in one DB query.
How it works
- Uses database-native ON DUPLICATE KEY UPDATE / ON CONFLICT
- No prior select
- One query only
Requirements
- ⚠️ Database-level unique index is mandatory
- You must specify:
- Unique column(s)
- Columns allowed to update
Key points
- 🚀 Extremely fast
- 🚀 Safe from race conditions
- ❌ No model events
- ❌ No observers
- ❌ No casts/mutators
Use it when
- Bulk imports
- Syncing APIs
- Logs, analytics, large datasets
- Performance matters more than model logic
Understanding this saves you from performance issues before they show up in production.
If you’re building with Laravel, this distinction is worth remembering.