{"id":25169674,"url":"https://github.com/sumup/typeid","last_synced_at":"2026-02-13T00:12:49.908Z","repository":{"id":239885527,"uuid":"753628081","full_name":"sumup/typeid","owner":"sumup","description":"TypeIDs are type-safe, globally unique identifiers based on UUIDv7 and UUIDv4 standard.","archived":false,"fork":false,"pushed_at":"2025-05-03T18:45:42.000Z","size":108,"stargazers_count":20,"open_issues_count":3,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-03T19:37:23.021Z","etag":null,"topics":["go","ids","typeid"],"latest_commit_sha":null,"homepage":"","language":"Go","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/sumup.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-02-06T13:54:32.000Z","updated_at":"2025-04-05T15:24:08.000Z","dependencies_parsed_at":"2024-05-15T23:03:06.250Z","dependency_job_id":"9973c3a5-928b-49cb-b434-1f7b9d26bcdf","html_url":"https://github.com/sumup/typeid","commit_stats":null,"previous_names":["sumup/typeid"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumup%2Ftypeid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumup%2Ftypeid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumup%2Ftypeid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumup%2Ftypeid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sumup","download_url":"https://codeload.github.com/sumup/typeid/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252547024,"owners_count":21765893,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["go","ids","typeid"],"created_at":"2025-02-09T08:36:12.949Z","updated_at":"2026-02-13T00:12:49.902Z","avatar_url":"https://github.com/sumup.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# TypeID\n\n[![Stars](https://img.shields.io/github/stars/sumup/typeid?style=social)](https://github.com/sumup/typeid/)\n[![Go Reference](https://pkg.go.dev/badge/github.com/sumup/typeid.svg)](https://pkg.go.dev/github.com/sumup/typeid)\n[![CI Status](https://github.com/sumup/typeid/workflows/CI/badge.svg)](https://github.com/sumup/typeid/actions/workflows/ci.yml)\n[![License](https://img.shields.io/github/license/sumup/typeid)](./LICENSE)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.1%20adopted-ff69b4.svg)](https://github.com/sumup/typeid/tree/main/CODE_OF_CONDUCT.md)\n\n\u003c/div\u003e\n\nTypeIDs are a draft standard for *type-safe, globally unique identifiers* based on the [UUIDv7 standard](https://datatracker.ietf.org/doc/html/rfc9562). Their properties, particularly k-sortability, make them suitable primary identifiers for classic database systems like PostgreSQL. However, k-sortability may not always be desirable. For instance, you might require an identifier with high randomness entropy for security reasons. Additionally, in distributed database systems like CockroachDB, having a k-sortable primary key can lead to hotspots and performance issues.\n\nWhile this package draws inspiration from the original typeid-go package ([github.com/jetify-com/typeid-go](https://github.com/jetify-com/typeid-go)), it provides multiple ID types:\n\n- `typeid.Sortable` is based on UUIDv7[^UUIDv7] and is k-sortable. Its implementation adheres to the draft standard. The suffix part is encoded in **lowercase** crockford base32.\n- `typeid.Random` is also based on UUIDv4[^UUIDv4] and is completely random. Unlike `typeid.Sortable`, the suffix part is encoded in **uppercase** crockford base32.\n\nPlease refer to the respective type documentation for more details.\n\n## Install\n\n```shell\ngo get github.com/sumup/typeid\n```\n\n# Usage\n\nTo create a new ID type, define a prefix type that implements the `typeid.Prefix` interface. Then, define a TypeAlias for your ID type to `typeid.Random` or `typeid.Sortable` with your prefix type as generic argument.\n\nExample:\n\n```go\nimport \"github.com/sumup/typeid\"\n\ntype UserPrefix struct{}\n\nfunc (UserPrefix) Prefix() string {\n    return \"user\"\n}\n\ntype UserID = typeid.Sortable[UserPrefix]\n\nuserID, err := typeid.New[UserID]()\nif err != nil {\n    fmt.Println(\"create user id:\", err)\n}\n\nfmt.Println(userID) // --\u003e user_01hf98sp99fs2b4qf2jm11hse4\n```\n\n# Database Support\n\nID types in this package can be used with [database/sql](https://pkg.go.dev/database/sql) and [github.com/jackc/pgx](https://pkg.go.dev/github.com/jackc/pgx/v5).\n\nWhen using the standard library SQL, IDs will be stored as their string representation and can be scanned and valued accordingly. When using pgx, both TEXT and UUID columns can be used directly. However, note that the type information is lost when using UUID columns, unless you take additional steps at the database layer. Be mindful of your identifier semantics, especially in complex JOIN queries.\n\nIf using `pgx` with PostgreSQL, you can generate UUIDv4 (for usage with `typeid.Random`) as the default value for your primary key:\n\n```sql\nCREATE TABLE users (\n    id UUID PRIMARY KEY DEFAULT GEN_RANDOM_UUID(),\n    ...\n);\n```\n\nFor k-sortable TypeIDs (`typeid.Sortable`, using UUIDv7) you will have to generate the UUID in your application unless you are running [PostgreSQL 18](https://www.thenile.dev/blog/uuidv7) or new where both are supported:\n\n```sql\n-- With random TypeID\nCREATE TABLE users (\n    id UUID PRIMARY KEY DEFAULT uuidv4(),\n    ...\n);\n\n-- With sortable TypeID\nCREATE TABLE users (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),\n    ...\n);\n```\n\n## Using with sqlc\n\nTypeIDs work seamlessly with [sqlc](https://sqlc.dev/) by using column overrides in your `sqlc.yaml` configuration:\n\n```yaml\nversion: \"2\"\nsql:\n  - schema: \"schema.sql\"\n    queries: \"queries\"\n    engine: postgresql\n    gen:\n      go:\n        package: postgres\n        out: postgres\n        sql_package: pgx/v5\n        overrides:\n          - column: users.id\n            go_type:\n              import: github.com/yourorg/yourproject/internal/domain\n              type: \"UserID\"\n```\n\nWith this configuration, sqlc will generate Go code that uses your TypeID type directly:\n\n```go\npackage domain\n\nimport \"github.com/sumup/typeid\"\n\ntype UserPrefix struct{}\n\nfunc (UserPrefix) Prefix() string {\n    return \"user\"\n}\n\ntype UserID = typeid.Sortable[UserPrefix]\n\ntype User struct {\n    ID          UserID\n    Name        string\n    // ... other fields\n}\n```\n\nYou can then use your TypeID types directly in your queries:\n\n```sql\n-- name: CreateUser :one\nINSERT INTO users (\n    id,\n    name\n) VALUES (\n    @id,\n    @name\n) RETURNING *;\n\n-- name: GetUser :one\nSELECT * FROM users\nWHERE id = @id;\n```\n\nAnd call them from Go:\n\n```go\nuserID := typeid.Must(typeid.New[domain.UserID]())\nuser, err := queries.CreateUser(ctx, postgres.CreateUserParams{\n    ID:          userID,\n    Name:        \"Karl\",\n})\n```\n\n## Using with oapi-codegen\n\nTypeIDs can be used with [oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) to generate type-safe API clients and servers. Use the `x-go-type` and `x-go-type-import` extensions in your OpenAPI specification:\n\n```yaml\npaths:\n  /users/{user_id}:\n    parameters:\n      - in: path\n        name: user_id\n        description: The ID of the uesr to retrieve.\n        required: true\n        schema:\n          type: string\n          example: user_01hf98sp99fs2b4qf2jm11hse4\n          x-go-type: \"domain.UserID\"\n          x-go-type-import:\n            path: github.com/yourorg/yourproject/internal/domain\n\ncomponents:\n  schemas:\n    User:\n      type: object\n      properties:\n        id:\n          type: string\n          description: Unique identifier of the user.\n          example: user_01hf98sp99fs2b4qf2jm11hse4\n          x-go-type: \"domain.UserID\"\n          x-go-type-import:\n            path: github.com/yourorg/yourproject/internal/domain\n        name:\n          type: string\n```\n\nThe generated code will use your TypeID types:\n\n```go\ntype User struct {\n    Id   domain.UserID `json:\"id\"`\n    Name string        `json:\"name\"`\n}\n```\n\nTypeIDs implement `encoding.TextMarshaler` and `encoding.TextUnmarshaler`, so they work with JSON encoding/decoding in generated API code without any additional configuration.\n\n### Maintainers\n\n- [Johannes Gräger](mailto:johannes.graeger@sumup.com)\n- [Matouš Dzivjak](mailto:matous.dzivjak@sumup.com)\n\n---\n\nBased on the go implementation of typeid found at: https://github.com/jetify-com/typeid-go by [Jetify](https://www.jetify.com/).\nModifications made available under the same license as the original.\n\n[^UUIDv7]: https://datatracker.ietf.org/doc/html/rfc9562\n[^UUIDv4]: https://datatracker.ietf.org/doc/html/rfc4122\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumup%2Ftypeid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsumup%2Ftypeid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumup%2Ftypeid/lists"}