php-snowflake turns the Twitter ID scheme into a PHP service
❄ An ID Generator for PHP based on Snowflake Algorithm (Twitter announced).
At a glance
- What is it?
- php-snowflake is a PHP implementation of the Snowflake and Sonyflake algorithms that packs a timestamp, a datacenter id, a worker id and a per-millisecond sequence into a single integer, and it makes the sequence number pluggable so you can choose how concurrency is handled.
- Who is it for?
- php-snowflake suits a PHP team that wants database primary keys that sort by time, avoids a round trip to a sequence service, and needs the sequence strategy to match the infrastructure it already runs, whether that is Redis, the Laravel cache or a local file lock.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The 64 bit layout: sign, 41 bit time, 5 plus 5 node, 12 bit sequence
The core of php-snowflake is the Snowflake layout described in the README, and every constraint of the library follows from it. The first bit is an unused sign bit. The second part is a 41 bit timestamp in milliseconds, representing the offset of the current time relative to a chosen reference time. The third and fourth parts are 5 bits each for the data center id and the worker id, with a maximum of 31 for both, which is 2^5 minus 1. The last 12 bits hold the serial number generated per millisecond per working node, so a single node can produce at most 4095 ids in one millisecond before it has to wait. The 41 bit timestamp field is what gives the ids their time ordering, and the README notes that it can represent up to 69 years, which is why it suggests setting a start time to make the most of the window.
The sequence resolver is where concurrency actually lives
The problem with Snowflake is not the timestamp, it is the last 12 bits. If two requests in the same millisecond on the same node pick the same sequence number, they produce the same id. The README states the requirement directly: sequence numbers generated within the same millisecond on the same node must be unique. This package therefore ships several sequence number providers and lets you choose one, and this is the real decision you make when adopting it. RandomSequenceResolver is listed as random and explicitly unsafe. FileLockResolver uses the PHP file lock functions fopen and flock. RedisSequenceResolver and PredisSequenceResolver use Redis psetex and incrby operations. LaravelSequenceResolver uses the Laravel cache add lock mechanism. SwooleSequenceResolver uses swoole_lock. The default resolver is not stated in the README, so a reader should not assume which one is active before setting one explicitly.
Installing the package and the resolver you actually need
The package requires PHP 8.1 or newer and Composer, and it is installed from Packagist.
$ composer require godruoyi/php-snowflake -vvv
# Install `predis/predis` package if you are using PredisSequenceResolver
$ composer require "predis/predis"
# Install `Redis` extensions if you are using RedisSequenceResolver
$ pecl install redis
# Install `Swoole` extensions if you are using SwooleSequenceResolver
$ pecl install swooleThose three optional installs are the only infrastructure the package asks for, and each maps to one resolver. The FileLockResolver and LaravelSequenceResolver need nothing beyond PHP, which is what makes the package usable in a plain application with no extra services running.
The first use is three lines.
$snowflake = new \Godruoyi\Snowflake\Snowflake;
$snowflake->id();
// 1537200202186752That value is an example in the README, not a measurement, but the shape is what matters: a single integer that grows with time.
Setting the datacenter, worker and start time before you generate ids
Three constructor and setter options exist, and one of them is easy to skip and expensive to skip. The datacenter and worker ids are constructor arguments, and the README notes the 31 value ceiling for both, so across your estate you need an allocation scheme that never hands the same pair to two live processes.
$snowflake = new \Godruoyi\Snowflake\Snowflake($datacenterId, $workerId);
$snowflake->id();The start time is set separately and determines what the timestamp offset is measured from.
$snowflake = new \Godruoyi\Snowflake\Snowflake;
$snowflake->setStartTimeStamp(strtotime('2019-09-09')*1000); // millisecond
$snowflake->id();The setStartTimeStamp method takes milliseconds, which is why the example multiplies a strtotime result by 1000. A later variant of the algorithm, Sonyflake, is available in the same namespace as a separate class and is selected by instantiating it instead of Snowflake. The README does not document in the English version what differs between the two beyond the name, so treat Sonyflake as the alternative bit layout rather than assume its properties.
Wiring the sequence resolver into a Laravel service provider
There is no official Laravel extension, and the README says so plainly, giving integration steps instead. The pattern is to register the generator as a container singleton so that one instance is shared for the lifetime of the application and the sequence state is not reset between requests.
// App\Providers\AppServiceProvider
use Godruoyi\Snowflake\Snowflake;
use Godruoyi\Snowflake\LaravelSequenceResolver;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('snowflake', function ($app) {
return (new Snowflake())
->setStartTimeStamp(strtotime('2019-10-10')*1000)
->setSequenceResolver(new LaravelSequenceResolver($app->get('cache.store')));
});
}
}The resolver is handed the application's cache store, so the sequence counter lives in whatever cache backend Laravel is configured with. That choice has a consequence worth understanding: the safety of id generation now depends on that cache backend's atomicity and availability, not only on PHP. If the cache store is a local file or array store and you run more than one application node, the per-millisecond counters are no longer shared.
Writing your own resolver or passing a closure
For anything the built-in providers do not cover, the extension point is the SequenceResolver interface, and a closure works as well as a class.
$snowflake = new \Godruoyi\Snowflake\Snowflake;
$snowflake->setSequenceResolver(function ($currentMillisecond) {
static $lastTime;
static $sequence;
if ($lastTime == $currentMillisecond) {
++$sequence;
} else {
$sequence = 0;
}
$lastTime = $currentMillisecond;
return $sequence;
})->id();The closure keeps the last timestamp and the counter in static variables, which is the textbook implementation and is only safe inside a single process. The README also shows a class implementing the interface with a sequence method taking the current millisecond, with a comment marking it as a test returning mt_rand. Implementing this interface for a distributed setup means implementing your own atomic increment, which is the same work the bundled resolvers already do.
A release history and a licence that keeps the choice simple
php-snowflake is published under the MIT licence, with the LICENSE file in the repository root, and the package is available on Packagist as godruoyi/php-snowflake. The tagged releases are 3.2.3 from 2026-04-23, 3.2.2 from 2026-01-31 and 3.2.1 from 2025-05-01, and the last push was on 2026-04-23, the same day as the newest tag. The repository also carries a Chinese version of the readme in README-zh_CN.md, a phpstan.neon.dist configuration, a phpunit.xml.dist, a pint.json formatting configuration and a stubs directory, which together suggest that static analysis and formatting are part of the project's own workflow rather than left to the consumer. The release dates alone tell you little about what changed between 3.2.1 and 3.2.2, so check the changelog before upgrading.
Editorial conclusion
php-snowflake suits a PHP team that wants database primary keys that sort by time, avoids a round trip to a sequence service, and needs the sequence strategy to match the infrastructure it already runs, whether that is Redis, the Laravel cache or a local file lock. It is the wrong choice if you need globally unique identifiers across data centres without coordinating datacenter and worker ids, since the algorithm requires that those values never collide, and the wrong choice for a single-process script that just needs a random unique string. Before adopting it, decide the datacenter and worker id allocation scheme for every instance that will generate ids, pick a sequence resolver that matches your concurrency model, and set a start timestamp with setStartTimeStamp so the 41 bit window starts where you want it. The last push was on 2026-04-23 and the current release is 3.2.3 from the same day.
Frequently asked questions
How do I install php-snowflake with Composer?
Run composer require godruoyi/php-snowflake -vvv. The package needs PHP 8.1 or newer and Composer, and you additionally need predis/predis, the Redis extension or the Swoole extension only if you choose the matching sequence resolver.
What is a sequence resolver in php-snowflake and which one should I use?
The sequence resolver decides how the 12 bit per-millisecond counter is allocated, which is what keeps ids unique within one millisecond on one node. The package ships RandomSequenceResolver, which the README marks unsafe, plus FileLockResolver, RedisSequenceResolver, PredisSequenceResolver, LaravelSequenceResolver and SwooleSequenceResolver.
How do I set the start time for generated IDs?
Call setStartTimeStamp with a millisecond value, for example $snowflake->setStartTimeStamp(strtotime('2019-09-09')*1000). The README notes the 41 bit timestamp can cover up to 69 years and recommends setting a start time.
Can I use php-snowflake in a Laravel application?
Yes. The README states that no specific Laravel extension is offered, but shows how to register the generator as a container singleton in AppServiceProvider using LaravelSequenceResolver with the application cache store.
What is the difference between Snowflake and Sonyflake in php-snowflake?
Both classes exist in the Godruoyi\Snowflake namespace and both produce a single id from a call to id(). The English README documents the Snowflake bit layout in detail but does not spell out how the Sonyflake layout differs, so check the source before assuming the same properties hold.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/godruoyi-php-snowflake)Was this useful?