{"id":13871934,"url":"https://github.com/karwa/uniqueid","last_synced_at":"2026-02-18T22:01:30.122Z","repository":{"id":41828245,"uuid":"424171375","full_name":"karwa/uniqueid","owner":"karwa","description":"Random and time-ordered UUID generation in Swift","archived":false,"fork":false,"pushed_at":"2022-04-27T23:08:05.000Z","size":412,"stargazers_count":76,"open_issues_count":2,"forks_count":12,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-02-02T23:16:18.470Z","etag":null,"topics":["guid","sorted","sorted-lists","time-series","timeline","unique-id","unique-identifier","uuid"],"latest_commit_sha":null,"homepage":"https://karwa.github.io/uniqueid/main/documentation/uniqueid/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karwa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["karwa"]}},"created_at":"2021-11-03T09:59:24.000Z","updated_at":"2025-12-01T13:18:00.000Z","dependencies_parsed_at":"2022-09-10T23:02:29.648Z","dependency_job_id":null,"html_url":"https://github.com/karwa/uniqueid","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/karwa/uniqueid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karwa%2Funiqueid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karwa%2Funiqueid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karwa%2Funiqueid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karwa%2Funiqueid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karwa","download_url":"https://codeload.github.com/karwa/uniqueid/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karwa%2Funiqueid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29596329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T20:59:56.587Z","status":"ssl_error","status_checked_at":"2026-02-18T20:58:41.434Z","response_time":162,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["guid","sorted","sorted-lists","time-series","timeline","unique-id","unique-identifier","uuid"],"created_at":"2024-08-05T23:00:30.722Z","updated_at":"2026-02-18T22:01:30.106Z","avatar_url":"https://github.com/karwa.png","language":"Swift","funding_links":["https://github.com/sponsors/karwa"],"categories":["Swift"],"sub_categories":[],"readme":"# UniqueID\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fkarwa%2Funiqueid%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/karwa/uniqueid) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fkarwa%2Funiqueid%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/karwa/uniqueid)\n\nUUIDv4 and v6\\* generation in Swift.\n\n[[Documentation](https://karwa.github.io/uniqueid/main/documentation/uniqueid)]\n\nA UUID is an identifier that is unique across both space and time, with respect to the space of all UUIDs. They are used for multiple purposes, from tagging objects with an extremely short lifetime, to reliably identifying very persistent objects across a network.\n\n`UniqueID` supports any 128-bit UUID, and is fully compatible with Foundation's `UUID`.\nIt also includes features to generate 2 kinds of ID:\n\n- **Random**: As defined in [RFC-4122][RFC-4122-UUIDv4] (UUIDv4).\n\n  A 128-bit identifier, consisting of 122 random bits.\n  These are the most common form of UUIDs; for example, they are the ones Foundation's `UUID` type creates\n  by default. To generate a random UUID, call the static `random()` function.\n\n  ```swift\n  for _ in 0..\u003c3 {\n    print(UniqueID.random())\n  }\n\n  \"DFFC75B4-C92F-4DA9-97CA-7F0EEF067FF2\"\n  \"67E5F28C-5083-4908-BD69-D7E27C8BABA4\"\n  \"3BA8EEF0-DFBE-4AE0-A646-E165FCA9054C\"\n  ```\n\n- **Time-Ordered**: Generated according to a [draft update of RFC-4122][UUIDv6-draft-02] (UUIDv6).\n\n  A 128-bit identifier, consisting of a 60-bit timestamp with 100ns precision, a 14-bit sequencing number seeded\n  from random bits, and a 48-bit node ID (which may also be random bits). To generate a time-ordered UUID,\n  call the static `timeOrdered()` function.\n\n  ```swift\n  for _ in 0..\u003c3 {\n    print(UniqueID.timeOrdered())\n  }\n  \n  \"1EC3C81E-A361-658C-BB38-65AAEF71CFCF\"\n  \"1EC3C81E-A361-6F6E-BB38-6DE69B9BCA1B\"\n  \"1EC3C81E-A362-698C-BB38-050642A95C73\"\n   |------------- --| |--| |----------|\n       timestamp       sq      node\n  ```\n\n  As you can see, time-ordered UUIDs generated in sequence share a common prefix (from the timestamp), yet\n  retain high collision avoidance. This allows the use of sorted data structures and algorithms\n  such as binary search, as an alternative to hash tables. They are far more efficient than random UUIDs for use\n  as database primary keys.\n\n\u003e Tip:\n\u003e Random and Time-Ordered UUIDs may coexist in the same database.\n\u003e They have different version numbers, so they are guaranteed to never collide.\n\n[RFC-4122-UUIDv4]: https://datatracker.ietf.org/doc/html/rfc4122#section-4.4\n[UUIDv6-draft-02]: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-02\n\n# Using UniqueID in your project\n\nTo use this package in a SwiftPM project, you need to set it up as a package dependency:\n\n```swift\n// swift-tools-version:5.5\nimport PackageDescription\n\nlet package = Package(\n  name: \"MyPackage\",\n  dependencies: [\n    .package(\n      url: \"https://github.com/karwa/uniqueid\",\n      .upToNextMajor(from: \"1.0.0\")\n    )\n  ],\n  targets: [\n    .target(\n      name: \"MyTarget\",\n      dependencies: [\n        .product(name: \"UniqueID\", package: \"uniqueid\")\n      ]\n    )\n  ]\n)\n```\n\nAnd with that, you're ready to start using `UniqueID`. One way to get easily experiment with time-ordered (v6) UUIDs is to use Foundation compatibility to simply change how you create UUIDs:\n\n```swift\nimport Foundation\nimport UniqueID\n\n// Change from UUID() to UUID(.timeOrdered()).\nstruct MyRecord {\n  var id: UUID = UUID(.timeOrdered())\n  var name: String\n}\n\n// Read the timestamp by converting to UniqueID.\nlet uniqueID = UniqueID(myRecord.id)\nprint(uniqueID.components(.timeOrdered)?.timestamp)\n```\n\nBear in mind that v6 UUIDs are not yet an official standard, and the layout may change before it becomes an approved internet standard. This implementation aligns with draft 02, from 7 October 2021. Check the latest status [here](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-02).\n\n\n## Why new UUIDs?\n\nThe IETF draft has a really good summary of why using time-ordered UUIDs can be beneficial. You should read it - at least [the \"Background\" section](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-02#section-2).\n\n\u003e A lot of things have changed in the time since UUIDs were originally\n\u003e created.  Modern applications have a need to use (and many have\n\u003e already implemented) UUIDs as database primary keys.\n\u003e\n\u003e The motivation for using UUIDs as database keys stems primarily from\n\u003e the fact that applications are increasingly distributed in nature.\n\u003e Simplistic \"auto increment\" schemes with integers in sequence do not\n\u003e work well in a distributed system since the effort required to\n\u003e synchronize such numbers across a network can easily become a burden.\n\u003e The fact that UUIDs can be used to create unique and reasonably short\n\u003e values in distributed systems without requiring synchronization makes\n\u003e them a good candidate for use as a database key in such environments.\n\u003e\n\u003e However some properties of RFC4122 UUIDs are not well suited to\n\u003e this task.  First, most of the existing UUID versions such as UUIDv4\n\u003e have poor database index locality.  Meaning new values created in\n\u003e succession are not close to each other in the index and thus require\n\u003e inserts to be performed at random locations.  The negative\n\u003e performance effects of which on common structures used for this\n\u003e (B-tree and its variants) can be dramatic.  As such newly inserted\n\u003e values SHOULD be time-ordered to address this.\n\nPrevious time-ordered UUIDs, such as version 1 UUIDs from RFC-4122, store their timestamps in a convoluted format, so you can't just sort UUIDs based on their bytes and arrive at a time-sorted list of UUIDs. Version 6 improves on that.\n\nLet's compare 10 UUIDv4s against 10 UUIDv6s:\n\n```\nfor _ in 0..\u003c10 {\n  print(UniqueID.random())\n}\n\nDFFC75B4-C92F-4DA9-97CA-7F0EEF067FF2\n67E5F28C-5083-4908-BD69-D7E27C8BABA4\n3BA8EEF0-DFBE-4AE0-A646-E165FCA9054C\nDF92B4B0-F5EE-42E5-9577-A9FC373C71A4\nA2F8DD26-D513-4AE6-9E5C-58363885CCB6\nBB0B5841-2BC0-49E2-BC5C-362CC34D7225\nB08AF1F7-E2D3-4175-913D-369140612FF5\nA453FB62-DF71-436F-9AC1-0414793DFA16\n485EEB84-A4BA-44FE-BE3B-AD90390B0523\n8A9AE1FA-4104-442C-B459-8F682E77F2F4\n``` \n\n```\nfor _ in 0..\u003c10 {\n  print(UniqueID.timeOrdered())\n}\n\n1EC3C81E-A35C-69E2-BB38-EDDC5E7E5F5E\n1EC3C81E-A361-658C-BB38-65AAEF71CFCF\n1EC3C81E-A361-6F6E-BB38-6DE69B9BCA1B\n1EC3C81E-A362-698C-BB38-050642A95C73\n1EC3C81E-A363-6152-BB38-F105ED78927F\n1EC3C81E-A363-6A94-BB38-4DAB2CAE46CD\n1EC3C81E-A364-63D6-BB38-6114031916EF\n1EC3C81E-A364-6D04-BB38-435A854C2E42\n1EC3C81E-A365-66AA-BB38-03504FA2F6FE\n1EC3C81E-A365-6F74-BB38-1F5AE9E10389\n```\n\nBoth lists are unique, and unique with respect to each other, but the time-ordered ones, naturally, came out in order of creation time. We can even extract the embedded timestamp - in this case, it says the UUID was created on the 3rd of November, 2021 at 08:42:01 UTC (down to 100ns precision, theoretically).\n\nThe combination of temporal and spacial components means these UUIDs are still robust to collisions - a new 60-bit universe exists every 100ns, and the IDs within that universe are still alloted based on random bits with high entropy. It's tempting to think you might be paying a high cost in collisions for the ease of use, but it's not as simple as that.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarwa%2Funiqueid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarwa%2Funiqueid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarwa%2Funiqueid/lists"}