Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Mick79's avatar

UUID as primary key type?

I was wondering why Laravel doesn't give UUID as a default option for the ID column in any new table?

As I type into PHPStorm UUID is an option, but it doesn't work.

Anyone know why?

0 likes
9 replies
martinbean's avatar
Level 80

@Mick79 It’s not the default because probably more than 90% of projects use auto-incrementing integers as primary keys in databases.

You can use UUIDs as your Eloquent models’ ID. You need to set the $keyType property to string, and then $incrementing to false. You’ll also need to set $primaryKey if you call your primary key column something other than id. Finally, hook into your model’s creating method to generate a UUID:

use Ramsey\Uuid\Uuid;

class Foo extends Model
{
    protected $primaryKey = 'uuid';

    protected $keyType = 'string';

    public $incrementing = false;

    protected static function boot()
    {
        parent::boot();

        static::creating(function (Model $model) {
            $model->setAttribute($model->getKeyName(), Uuid::uuid4());
        });
    }
}
17 likes
Mick79's avatar

Thanks a lot Martin. I was under the impression that using UUID was a much better idea than standard increments due to potential problems if you ever need to copy tables to another database at any point in the future.

gregrobson's avatar

Exports of databases should be unaffected - you can always restore with the same primary key values from when you backed up.

UUIDs can have advantages if you have a distributed system (IDs being generated across several separate machines/databases) and need a (near enough) guarantee of uniqueness across the whole system.

There are several drawbacks though.

  • It's 16 bytes instead of an integer's 4 or bigint's 8. That takes up more disk for the data and the indexes.
  • ...it therefore requires more RAM to hold cached UUIDs in memory.
  • ...and any joins that involve UUIDs require more memory.
  • "UUID index fragmentation" ... as the UUIDs are not generated sequentially like integer primary keys the index will be messier and tend to suffer from more bloat.
  • If you want to sort by the order records were generated, sorting by primary key is the easiest if you use integers: UUIDs won't sort into a logical order as they generated at random.

Pinterest avoided UUIDs and used 64 bit integers in a customised way when they needed uniqueness against all their servers: https://medium.com/@Pinterest_Engineering/sharding-pinterest-how-we-scaled-our-mysql-fleet-3f341e96ca6f

Takeaway: UUIDs have there uses, but they are typically rare :-)

7 likes
afraz's avatar

Create Traits directory in App\Models Directory

namespace App\Models\Traits;


use Illuminate\Database\Eloquent\Model;

use Ramsey\Uuid\Uuid;


trait HasUniqueIdentifier{

public static function boot()

{
    parent::boot();

    static::creating(function (Model $model) {


        $model->setKeyType('string');

        $model->setIncrementing(false);

        $model->setAttribute($model->getKeyName(), Uuid::uuid4());

    });
}

}

Now in Model.

...

use HasUniqueIdentifier;

...

That's it.

3 likes
CryDeTaan's avatar

This is so clean, wish I have seen this years ago.

Although, as Ramsey's Uuid is now part of Laravel, and can be accessed using the Str helper I opted for the following setAttribute

$model->setAttribute($model->getKeyName(), Str::uuid());

CryDeTaan's avatar

I have actually been having some issues with it when configuring the primary key using the creating observer. Specifically that the id would be cast to int and I therefore moved to overwriting the methods rather. I use a trait now as follow:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

trait HasUuid
{
    /**
     * Get the value indicating whether the IDs are incrementing.
     *
     * @return bool
     */
    public function getIncrementing()
    {
        return false;
    }

    /**
     * Get the auto-incrementing key type.
     *
     * @return string
     */
    public function getKeyType()
    {
        return 'string';
    }

    public static function booted()
    {
        static::creating(function (Model $model) {
            // Set attribute for new model's primary key (ID) to an uuid.
            $model->setAttribute($model->getKeyName(), Str::uuid());
        });
    }
}

3 likes
starter-dev's avatar

Cleaner way to do it:

// In migration file
Schema::create('users', function (Blueprint $table) {
    $table->uuid('id')->primary();
    // ....
});

Starting from Laravel 9, you can now add the HasUuids trait in model to automatically assign uuid to the primary key column:

// In model
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Concerns\HasUuids;

class User extends Authenticatable
{
    use HasFactory, Notifiable;
    use HasUuids; // Add this trait								
    // ....
}

Please or to participate in this conversation.