# How to Use Laravel Update or Create: The Efficient Upsert Pattern for Eloquent Models

> Master Laravel update or create with the efficient Eloquent "updateOrCreate" method. Atomically update or insert records, optimizing database queries and preventing race conditions.

- Repository: [Laravel/framework](https://github.com/laravel/framework)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use the `updateOrCreate` method on Eloquent models to atomically update existing records or insert new ones with minimal database queries and built-in race condition handling.**

When building applications with the `laravel/framework` repository, you frequently encounter scenarios where you need to either update an existing database record or create a new one if it does not exist. This **laravel update or create** pattern, commonly known as an "upsert," is implemented efficiently through Eloquent's dedicated builder methods that optimize query count and ensure transactional safety.

## How Laravel Update or Create Works Under the Hood

The `updateOrCreate` method is implemented in [`src/Illuminate/Database/Eloquent/Builder.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Builder.php) and provides a robust, race-condition-safe mechanism for handling upsert operations.

### The Single-Step API

The method signature `updateOrCreate(array $attributes, array $values = [])` accepts two parameters:

- **`$attributes`**: The criteria used to search for an existing record (typically unique keys like email or UUID)
- **`$values`**: The attributes to update or set on the found or newly created model

Internally, the method delegates to `firstOrCreate`, which executes a **SELECT** query to locate the record. If found, the model is returned immediately. If not found, the system attempts an **INSERT** operation.

### Transactional Safety and Race Condition Handling

The implementation uses database save-points via `withSavepointIfNeeded` to ensure atomicity. When two concurrent requests attempt to insert the same unique key simultaneously:

1. The first request successfully inserts the record
2. The second request catches the `UniqueConstraintViolationException`
3. The second request then fetches the existing record that was just created by the first request

This guarantees that only **one** INSERT is ever performed per unique key, even under heavy contention, while ensuring both requests receive a valid model instance.

### Query Efficiency

When updating an existing record, the method calls `fill()` with the `$values` array and then `save()`. Because the model is already loaded from the database, this issues only a single **UPDATE** query for the changed fields. The entire operation typically requires either:
- One SELECT + one UPDATE (existing record), or
- One SELECT + one INSERT (new record)

## Laravel Update or Create Examples

### Basic Usage

The most common pattern matches a unique identifier and updates specific fields while creating the record if it does not exist:

```php
use App\Models\User;

// Update the user if the email exists, otherwise create a new record
$user = User::query()->updateOrCreate(
    ['email' => 'jane@example.com'],              // Search attributes (unique key)
    ['name' => 'Jane Doe', 'is_active' => true]  // Values to set or update
);

```

### Dynamic Values with Closures

For complex logic or computed values, pass a closure as the second argument:

```php
$user = User::query()->updateOrCreate(
    ['email' => $request->email],
    fn () => [
        'name' => $request->name,
        'last_login_at' => now(),
        'login_count' => DB::raw('login_count + 1'),
    ]
);

```

### Relationship Operations

Eloquent relationships also expose the `updateOrCreate` method. For a `HasMany` relationship (e.g., a user has many phones):

```php
// UpdateOrCreate on a HasMany relationship
$user->phones()->updateOrCreate(
    ['type' => 'mobile'],
    ['number' => $request->mobile_number, 'verified_at' => now()]
);

```

For `BelongsToMany` relationships, the method handles pivot data automatically through the implementation in [`src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php).

### Bulk Operations with Upsert

When processing multiple records simultaneously, use the lower-level `upsert` method to minimize query count:

```php
// Bulk upsert for large batches
User::upsert(
    [
        ['email' => 'john@example.com', 'name' => 'John Smith'],
        ['email' => 'jane@example.com', 'name' => 'Jane Doe'],
        ['email' => 'bob@example.com', 'name' => 'Bob Wilson'],
    ],
    ['email'],              // Unique key(s) to match
    ['name']                // Columns to update if match found
);

```

The `upsert` method is available directly on the model and is distinct from `updateOrCreate`, which is designed for single-row operations.

## Key Implementation Files in Laravel Framework

The **laravel update or create** functionality is implemented across several core files in the `laravel/framework` repository:

- **[`src/Illuminate/Database/Eloquent/Builder.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Builder.php)** – Contains the primary `updateOrCreate` and `firstOrCreate` implementations, including the transactional save-point logic and exception handling for race conditions.

- **[`src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php)** – Provides relationship-specific `updateOrCreate` methods for `hasOne`, `hasMany`, and `morphMany` relations, automatically scoping queries to the parent model.

- **[`src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php)** – Implements `updateOrCreate` for many-to-many relationships, handling pivot table data and synchronization logic.

## Summary

- **Use `updateOrCreate`** for single-row upsert operations where you need to either update an existing record or create a new one based on unique attributes.
- **The method is race-condition safe** through the use of database save-points and exception handling for unique constraint violations.
- **It minimizes queries** by issuing either a SELECT + UPDATE or SELECT + INSERT, never more than two queries per operation.
- **For bulk operations**, use the `upsert` method instead to process multiple records in a single query.
- **Relationship methods** in [`HasOneOrMany.php`](https://github.com/laravel/framework/blob/main/HasOneOrMany.php) and [`BelongsToMany.php`](https://github.com/laravel/framework/blob/main/BelongsToMany.php) provide the same atomic guarantees for related models.

## Frequently Asked Questions

### What is the difference between updateOrCreate and firstOrCreate in Laravel?

`firstOrCreate` attempts to find a record matching the given attributes and creates it only if no match is found, using the same attributes for both searching and creation. `updateOrCreate` separates the search criteria from the update values, allowing you to match on specific keys (like email) while updating different fields (like name or timestamps). According to the source code in [`Builder.php`](https://github.com/laravel/framework/blob/main/Builder.php), `updateOrCreate` actually delegates to `firstOrCreate` internally but adds the additional step of filling and saving the model with the separate `$values` array.

### How does Laravel handle race conditions in updateOrCreate?

Laravel handles race conditions through a combination of database save-points and exception handling implemented in [`src/Illuminate/Database/Eloquent/Builder.php`](https://github.com/laravel/framework/blob/main/src/Illuminate/Database/Eloquent/Builder.php). When two concurrent requests attempt to insert the same unique key simultaneously, the second request catches the `UniqueConstraintViolationException`, rolls back only the save-point (leaving outer transactions intact), and then fetches the existing record that was created by the first request. This ensures that only one INSERT occurs while both requests receive a valid model instance.

### Is updateOrCreate atomic in Laravel?

Yes, `updateOrCreate` is atomic when used with database transactions. The method uses `withSavepointIfNeeded` to create a database save-point around the INSERT operation. If the INSERT fails due to a unique constraint violation, only the save-point is rolled back, not the entire transaction. This allows the operation to safely fall back to selecting the existing record without affecting surrounding database operations. However, the SELECT and UPDATE/INSERT combination itself is not a single SQL statement—it's two queries wrapped in transactional logic.

### When should I use upsert instead of updateOrCreate?

Use the `upsert` method instead of `updateOrCreate` when you need to process multiple records in a single operation to minimize database queries. While `updateOrCreate` is optimized for single-row operations (requiring up to two queries per row), `upsert` can insert or update many rows with a single query by leveraging the database's native upsert capabilities. According to the Laravel source, `upsert` is available directly on the model for bulk operations, whereas `updateOrCreate` is the idiomatic choice when dealing with individual model instances or relationship operations.