lastguest/murmurhash
A fast, dependency-free PHP implementation of MurmurHash (MurmurHash3) for non-cryptographic hashing. Generate consistent 32/128-bit hashes for sharding, caching keys, bloom filters, and partitioning. Simple API, Composer-ready, and easy to drop into Laravel or any PHP project.
Feature-level decisions
experiment_id + user_id gives a stable 0–99 bucket with no database lookup, no sticky-session infrastructure, and identical results across every app server, queue worker, and Lambda. This is the single highest-leverage use: it turns "we need a flags service" into afternoons of work.Roadmap-level decisions
hash('xxh3') vs. hand-rolling. The honest answer is that hand-rolling is a bad idea (easy to get wrong, silently), and this package is the cheapest credible option in pure PHP.Explicit non-decision
Strong fit
Hashing.murmur3_32 in Java, mmh3 in Python, Cassandra-style partitioning, Kafka's default partitioner (murmur2 — verify variant), or a data-warehouse pipeline that already buckets on murmur.Look elsewhere
hash('xxh3')/xxh128 (PHP 8.1+, in core, no dependency) or a C extension such as php-murmur if you need speed and don't need MurmurHash3 parity.murmur3_x64_128, plan on an extension.sodium_crypto_generichash, hash_hmac, or password_hash. Wrong tool entirely.Bucketer::bucket($key, $n), do not add a transitive dependency to a leaf service; ask them to swap the implementation.Adoption checklist if you proceed
composer.json; hashes are a data-format contract.Hasher::hash(string $key, int $seed): int) so the implementation can be swapped for xxh3 or an extension without touching call sites.For executives (30 seconds). We need a small, deterministic hashing utility to unblock consistent feature rollouts and horizontal sharding. The chosen option is a free, MIT-licensed, ~200-line library that ships as a normal Composer dependency — no vendor contract, no new infrastructure, no ops work. It is a commodity algorithm, not a strategic bet; the main risk is that it is unmaintained since 2021, which we mitigate by pinning the version and adding golden-value tests. Cost is a code review, not a budget line. It is explicitly not a security component and will not be used for passwords or tokens.
For engineering leads. It gives us deterministic bucketing — hash experiment_id + user_id, take modulo 100, get the same variant on every box forever, with no shared state. Same primitive covers cache-key generation, Bloom-filter hashing, and shard assignment, so one dependency serves several needs. Tradeoffs, plainly: pure PHP, so it is slow relative to native — fine for per-request hashing, not for bulk row-by-row passes; and if we are on PHP 8.1+ and don't need MurmurHash3 wire-compatibility with another service, hash('xxh3') is faster, in core, and a better default. The reason to pick this package over xxh3 is interop: matching an existing Java, Python, or pipeline implementation that already buckets on MurmurHash3. It's a stale repo — treat the code as frozen, wrap it behind our own Hasher interface, and add cross-implementation golden tests so a variant or endianness regression can't silently reshuffle tenants. If throughput or 64/128-bit output becomes a requirement, the interface lets us swap the backend without a migration.
The ask. One reviewer, one ADR, and a decision on whether we are standardizing on MurmurHash3 (interop-driven) or xxh3 (performance-driven). The wrong outcome is two teams picking differently and incompatible buckets.
How can I help you explore Laravel packages today?