Skip to main content

A Sonyflake implementation optimized for extreme usages.

Project description

A SonyFlake ID generator tailored for high-volume ID generation.

Installation

pip install sonyflake-turbo

Usage

Easy mode:

from sonyflake_turbo import SonyFlake

sf = SonyFlake(0x1337, 0xCAFE, start_time=1749081600)

print("one", next(sf))
print("n", sf(5))

for id_ in sf:
    print("iter", id_)
    break

Turbo mode:

from time import time_ns
from timeit import timeit

from sonyflake_turbo import MachineIDLCG, SonyFlake

get_machine_id = MachineIDLCG(time_ns())
EPOCH = 1749081600  # 2025-06-05T00:00:00Z

for count in [32, 16, 8, 4, 2, 1]:
    machine_ids = [get_machine_id() for _ in range(count)]
    sf = SonyFlake(*machine_ids, start_time=EPOCH)
    t = timeit(lambda: sf(1000), number=1000)
    print(f"Speed: 1M ids / {t:.2f}sec with {count} machine IDs")

Async:

import anyio
from sonyflake_turbo import AsyncSonyFlake, SonyFlake

sf = SonyFlake(0x1337, 0xCAFE, start_time=1749081600)
asf = AsyncSonyFlake(sf, sleep=anyio.sleep)  # defaults to asyncio.sleep

print("one", await asf)
print("n", await asf(5))

async for id_ in asf:
    print("aiter", id_)
    break

Important Notes

Vanilla SonyFlake Difference

In vanilla SonyFlake, whenever counter overflows, it simply waits for the next 10ms window. Which severely limits the throughput. I.e. single generator produces 256ids/10ms.

Turbo version is basically the same as vanilla SonyFlake, except it accepts more than one Machine ID in constructor args. On counter overflow, it advances to the next “unexhausted” Machine ID and resumes the generation. Waiting for the next 10ms window happens only when all of the Machine IDs were exhausted.

This behavior is not much different from having multiple vanilla ID generators in parallel, but by doing so we ensure produced IDs are always monotonically increasing (per generator instance) and avoid potential concurrency issues (by not doing concurrency).

Few other features in comparison to other SonyFlake implementations found in the wild:

  • Optional C extension module, for extra performance in CPython.

  • Async-framework-agnostic wrapper.

  • Thread-safe. Also has free-threading/nogil support [1].

Machine IDs

Machine ID is a 16 bit integer in range 0x0000 to 0xFFFF. Machine IDs are encoded as part of the SonyFlake ID:

Time

Machine ID

Counter

0x

0874AD4993 [2]

CAFE

04

SonyFlake IDs, in spirit, are UUIDv6, but compressed down to 64 bit. But unfortunately, we do not have luxury of having 48 bits for encoding node id (UUID equivalent of SonyFlake’s Machine ID). UUID standard proposes to use pseudo-random value for this field, which is sub-optimal for our case due to high risk of collisions.

Vanilla SonyFlake, on the other hand, used lower 16 bits of the private IP address. Which is sort of works, but has two major drawbacks:

  1. It assumes you have exactly one ID generator per machine in your network.

  2. You’re leaking some of your infrastructure info.

In the modern world (k8s, “lambdas”, etc…), both of these fall apart:

  1. Single machine often runs multiple different processes and/or threads. More often than not they’re isolated enough to be able to successfully coordinate ID generation.

  2. Security aspect aside, container IPs within cluster network are not something globally unique, especially if trimmed down to 16 bit.

Solving this issue is up to you, as a developer. This particular library does not include Machine ID management logic, so you are responsible for coordinating Machine IDs in your deployment.

Task is not trivial, but neither is impossible. Here are a few ideas:

  • Coordinate ID assignment via something like etcd or ZooKeeper using lease pattern. Optimal, but a bit bothersome to implement.

  • Reinvent Twitter’s SnowFlake by having a centralized service/sidecar. Extra round-trips SonyFlake intended to avoid.

  • Assign Machine IDs manually. DevOps team will hate you.

  • Use random Machine IDs. If I ignore it, maybe it will go away.jpg

But nevertheless, it has one helper class: MachineIDLCG. This is a primitive LCG-based 16 bit PRNG. It is intended to be used in tests, or in situations where concurrency is not a problem (e.g. desktop or CLI apps). You can also reuse it for generating IDs for a lease to avoid congestion when going etcd/ZooKeeper route.

How many Machine IDs you want to allocate per generator is something you should figure out on your own. Here’s some numbers for you to start (generating 1 million SonyFlake IDs):

Time

Machine IDs

1.22s

32

2.44s

16

4.88s

8

9.76s

4

19.53s

2

39.06s

1

Clock Rollback

There is no logic to handle clock rollbacks or drift at the moment. If clock moves backward, it will sleep() (await sleep() in async wrapper) until time catches up to last timestamp.

Start Time

SonyFlake ID has 39 bits dedicated for the time component with a resolution of 10ms. The time is stored relative to start_time. By default it is 1409529600 (2014-09-01T00:00:00Z), but you may want to define your own “epoch”.

Motivation

Sometimes you have to bear with consequences of decisions you’ve made long time ago. On a project I was leading, I made a decision to utilize SonyFlake. Everything was fine until we needed to ingest a lot of data, very quickly.

A flame graph showed we were sleeping way too much. The culprit was SonyFlake library we were using at that time. Some RTFM later, it was revealed that the problem was somewhere between the chair and keyboard.

Solution was found rather quickly: just instantiate more generators and cycle through them about every 256 IDs. Nothing could go wrong, right? Aside from fact that hack was of questionable quality, it did work.

Except, we’ve got hit by Hyrum’s Law. Unintentional side effect of the hack above was that IDs lost its “monotonically increasing” property [3]. Ofc, some of our and other team’s code were dependent on this SonyFlake’s feature. Duh.

Adding even more workarounds like pre-generate IDs, sort them and ingest was a compelling idea, but I did not feel right. Hence, this library was born.

Why should I use it?

If you’re starting a new project, please use UUIDv7. It is superior to SonyFlake in almost every way. It is an internet standard (RFC 9562), it is already available in various languages’ standard libraries and is supported by popular databases (PostgreSQL, MariaDB, etc…).

Otherwise you might want to use it for one of the following reasons:

  • You already use it and encountered similar problems mentioned in Motivation section.

  • You want to avoid extra round-trips to fetch IDs.

  • Usage of UUIDs is not feasible (legacy codebase, db indexes limited to 64 bit integers, etc…) but you still want to benefit from index locality/strict global ordering.

  • As a cheap way to reduce predicability of IDOR attacks.

  • Architecture lunatism is still strong within you and you want your code to be DDD-like (e.g. being able to reference an entity before it is stored in DB).

Development

Install:

python3 -m venv env
. env/bin/activate
pip install -r requirements-dev.txt
pip install -e .

Run tests:

pytest

Build wheels:

pip install cibuildwheel
cibuildwheel

Build a py3-none-any wheel (without the C extension):

SONYFLAKE_TURBO_BUILD=0 python -m build --wheel

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sonyflake_turbo-1.0.1.tar.gz (22.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sonyflake_turbo-1.0.1-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

sonyflake_turbo-1.0.1-cp310-abi3-win_amd64.whl (21.2 kB view details)

Uploaded CPython 3.10+Windows x86-64

sonyflake_turbo-1.0.1-cp310-abi3-win32.whl (20.9 kB view details)

Uploaded CPython 3.10+Windows x86

sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_x86_64.whl (21.4 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_aarch64.whl (22.3 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_x86_64.whl (21.0 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_aarch64.whl (22.5 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

sonyflake_turbo-1.0.1-cp310-abi3-macosx_11_0_arm64.whl (19.4 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file sonyflake_turbo-1.0.1.tar.gz.

File metadata

  • Download URL: sonyflake_turbo-1.0.1.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sonyflake_turbo-1.0.1.tar.gz
Algorithm Hash digest
SHA256 5706680739505c46ee5566de1464f95d1d842fabc7c14fd0b473f7fb47a04afc
MD5 ffa40c9667bcf2e0ea7a4c1b6b80a0bb
BLAKE2b-256 c4867b93ae087cec89e382bf63a5ff02de0faa4c9450f0df64485e1b00ffa800

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1.tar.gz:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 81e16941baefbac034aade282f911f5dcd39d8cd39261fabc68c96a18d6170e5
MD5 7d0d0f8cea1188133a474b905ae2e1d2
BLAKE2b-256 fff6da68b6a37c56f92c96bb5f0242ffd4e94ee1abe935b9fcc3d5099bce3063

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-py3-none-any.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 103795905312f14a2cd505ca6c7c990cfaa1607c2e20aaa9bf7a9bca17b2918b
MD5 2327a037d7071ff0d78e794892a8e644
BLAKE2b-256 33859f9aad20fe89102c32fdb409458211d5af981fe2c8ef762881ee00166e74

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-win_amd64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-win32.whl.

File metadata

  • Download URL: sonyflake_turbo-1.0.1-cp310-abi3-win32.whl
  • Upload date:
  • Size: 20.9 kB
  • Tags: CPython 3.10+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 15885e0f71d9bba5755335250be50daf3fc2f6aa27b155f38df0269edf565207
MD5 c74cb0464c54ccfcf7f1494d6b0db022
BLAKE2b-256 7591e461053a06eca8ebe4cab1233ac9293471125e84619deb73fc31293d2e30

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-win32.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c994091f3aff85ccca56e1c3e5c3b39c87bed5f3796736593e7ac220d74dbb49
MD5 85a19c52330ecbe15fdd0a79420f2253
BLAKE2b-256 2b8e74b0ec93678f8457e4b2325a9e8bade87c8c7c79e169586cd68f0b4efd27

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_x86_64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 55e87353c7829b79f715956cdf61777dae8365b36c35f75aafa4626ab8311fc8
MD5 87250983b8af50608891ffcb92de09b9
BLAKE2b-256 31db729495da475d5c7acae0a49161e45ad9322f24e1fc1633f49c2d2d47155e

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-musllinux_1_2_aarch64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 baceb7e5fe99a9abb3f5baec63855fab1de6923a3ce3f6d01be183d37a2c5edf
MD5 74a5e97a5b38776962383a35eac0ab87
BLAKE2b-256 84d2aa868160a660daf40c7db67606278d7688ecee31dc9d46235d15d4030230

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a7dea477ea83bd4e5c9145d7f5268c98d2f4a04815d795269610674b837b449e
MD5 cb6012d7831e3fc0a14a095ebcb7b351
BLAKE2b-256 0075a271bbb65a3bcacdfbfcc0c1aeb6de23ba98d5b2c1fd11955fee92f6878a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sonyflake_turbo-1.0.1-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for sonyflake_turbo-1.0.1-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bb7cf2d55313f77ec57d4cfed2466fe574c07cfb5afb290e2234ba81ab1379af
MD5 16f14ba52f6c4fd534a89ece61988a9a
BLAKE2b-256 35fa64a7d191d778ad621a8b23e5ccd3931c47d55c75771285b35194659b74d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for sonyflake_turbo-1.0.1-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on ZipFile/python-sonyflake-turbo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page