Works seamlessly with MySQL, MariaDB, and PostgreSQL — no MongoDB required.
Every Laravel developer has been there — you start a new project, define your migrations, and by default, your models use auto-incrementing IDs. It works fine... until your app grows, you need distributed systems, API integrations, or microservices. Suddenly, those integer IDs start to look like a limitation.
That’s where Laravel ObjectId comes in — a drop-in, ultra-fast, globally unique identifier system inspired by MongoDB’s ObjectIds, designed for MySQL, MariaDB, and PostgreSQL — no MongoDB required.
💡 Why ObjectId?
Unlike UUIDs or ULIDs, ObjectIds are compact 12-byte identifiers that encode timestamp, randomness, and a counter — making them sortable, lightweight, and unique across systems.
In numeric terms, they’re up to 3× faster to generate and smaller in size, which directly improves database performance and indexing.
✅ Works natively with MySQL, MariaDB, and PostgreSQL
🚫 No MongoDB driver or extension required
🧬 How ObjectId Works Internally
ObjectIds are 12-byte (96-bit) identifiers consisting of four key parts:
| Segment | Size | Description |
|---|---|---|
| Timestamp | 4 bytes | UNIX epoch seconds — makes IDs sortable by creation time |
| Machine Identifier | 5 bytes | Randomly generated, unique per host |
| Process ID | 2 bytes | Uniquely identifies the generating process |
| Counter | 3 bytes | Incrementing counter initialized randomly per process |
➡️ Total = 4 + 5 + 2 + 3 = 12 bytes = 24 hex characters
This design ensures uniqueness without any central generator and preserves chronological order, making it ideal for distributed systems.
For more details, check:
- MongoDB’s ObjectId Reference
- Percona’s Deep Dive into ObjectIds
- Stack Overflow breakdown of ObjectId structure
🧩 The Ecosystem
The Laravel package is built on top of our core PHP library:
- 🔹
wooserv/php-objectid: a pure PHP implementation of ObjectIds. - 🔹
wooserv/laravel-objectid: Laravel integration with automatic model ID assignment and migration macros.
Both packages are open-source under the MIT license, created by WooServ Labs.
⚡ Installation
composer require wooserv/laravel-objectid
🧱 Usage
Model Example
use WooServ\LaravelObjectId\Concerns\HasObjectIds;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasObjectIds;
}
Migration Example
Schema::create('posts', function (Blueprint $table) {
$table->objectId(); // Creates a 24-char string primary key
$table->string('title');
$table->timestamps();
});
Generate IDs Anywhere
$id = objectid(); // e.g. 6730b6a0d8a28f890b7c9f40
🔬 Benchmark Results
Laravel ObjectId Performance (10,000 iterations)
----------------------------------------------------------
ObjectId : 0.412 µs per ID
objectid() helper : 0.417 µs per ID
UUID : 1.283 µs per ID
ULID : 1.147 µs per ID
----------------------------------------------------------
Fastest: ObjectId 🚀
Database Insert Benchmark (1,000 inserts)
----------------------------------------------------------
ObjectId : 14.78 ms total (0.015 ms/insert)
UUID : 15.48 ms total (0.015 ms/insert)
ULID : 15.17 ms total (0.015 ms/insert)
----------------------------------------------------------
⚔️ ObjectId vs UUID vs ULID
| Feature | ObjectId | UUID | ULID |
|---|---|---|---|
| Length | 24 chars | 36 chars | 26 chars |
| Bytes | 12 | 16 | 16 |
| Sortable | ✅ (timestamp prefix) | ❌ | ✅ |
| Randomness | ✅ | ✅ | ✅ |
| Readability | 🟢 Compact | 🔴 Long | 🟢 Fair |
| Speed | 🚀 Fastest | 🐢 Slowest | ⚡ Medium |
| Works with MySQL/MariaDB/PostgreSQL | ✅ | ✅ | ✅ |
| Requires MongoDB | ❌ | ❌ | ❌ |
Verdict: ObjectId is the best balance between compactness, performance, and chronological order — and it’s fully compatible with standard SQL databases.
🧠 Why Developers Love It
- ✅ Automatic assignment — no need to manually generate IDs.
- ⚙️ Migration macro
$table->objectId()— clean and intuitive. - 🧩 Framework-agnostic core — works outside Laravel too.
- 📦 Compact storage — saves DB space compared to UUID.
- 🕒 Sortable by creation time — built-in timestamp encoding.
- 🧰 Database-compatible — works with MySQL, MariaDB, and PostgreSQL seamlessly.
🌍 Open Source Philosophy
Both packages are released under the MIT License and maintained by WooServ Labs, a collective of developers building open, high-performance PHP tooling for modern web apps.
We believe that open-source should be:
- Simple to install.
- Fun to use.
- Fast by default.
If you share that philosophy — star the repo, contribute, or just spread the word 💫
📎 Resources
- 🔗 Laravel ObjectId on GitHub
- 🔗 PHP ObjectId on GitHub
- 📦 Packagist: wooserv/laravel-objectid
- 📦 Packagist: wooserv/php-objectid
- 📘 MongoDB ObjectId Reference
⭐ If you like it — give it a Star on GitHub and share it with your fellow Laravel devs!
Top comments (6)
I never understood why people need to sort on id. In Laravel if you want to sort on timestamp use the created and updated columns. In the migrations they made a easy to use function to add them.
I do understand wanting to have an unique id, if you are at the stage that you need to divide tables over multiple instances. But you can do that with more proven technology.
The problem of having identifiable parts, is that it makes it weaker from a security perspective.
That is also why i have seen quite a few posts about the timestamp in UUID v7.
That’s a really good point — and totally valid for most Laravel apps 👏
You’re right: if you only need chronological sorting,
created_atdoes the job.But ObjectId targets a slightly different layer — index-level ordering and cross-table temporal consistency, especially when IDs are used externally (APIs, queues, logs, caching layers).
When IDs carry a time prefix, databases can keep index inserts sequential, reducing B-Tree fragmentation and write amplification.
It’s not about business sorting, but storage locality & index performance.
Regarding the timestamp visibility — absolutely, it’s a trade-off.
That’s why our upcoming binary mode will keep the timestamp component internal (not human-readable), while maintaining the same ordered properties.
Appreciate you bringing this up — that balance between readability, performance, and security is exactly what we’re exploring 🚀
At what point are relational databases suffering from B-Tree fragmentation?
And isn't the simple fix perodic index rebuilding?
That’s a great question — and you’re right, periodic index rebuilds do solve fragmentation in theory.
But in high-write or high-churn systems (think logs, events, order pipelines), fragmentation isn’t the only concern — it’s write amplification and page splits happening continuously.
When inserts aren’t sequential (like with random UUIDs), the B-Tree keeps rebalancing in memory, causing extra disk I/O and cache churn.
Sequential keys (like ObjectId or UUIDv7) keep inserts append-like, which maintains cache locality and improves throughput between rebuilds.
So yes — rebuilds help maintenance, but ordered IDs help avoid the constant micro-fragmentation in the first place.
Wouldn't it be better to use a database system that can handle those loads with less effort. I know the Postgres can do everything articles tell you otherwise.
But if you are in that situation changing the id format seems like a quick patch solution.
I'm not saying the format is a bad idea. It could be a solution for a specific case, and I'm glad it exists.
You're absolutely right — switching databases is usually the real long-term solution when scaling becomes a bottleneck.
Our goal with PHP & Laravel ObjectId isn’t to “fix” database limitations, but to offer a compact, timestamp-ordered ID format that works seamlessly inside existing systems — especially for teams that can’t migrate off MySQL yet, or need sortable unique keys in distributed setups.
PostgreSQL is definitely a powerhouse (and we benchmarked it too).
The nice part is: ObjectId performs identically across MySQL and Postgres, so developers can keep their stack while gaining predictable ordering and smaller index sizes.
It’s less of a “quick patch,” and more of a “drop-in upgrade” for people already invested in Laravel’s ecosystem.