Conversation
Add support for UUID v7 as an alternative ID format, configurable per tenant.
COMPARE TO
|
| Name | Diff |
|---|---|
| packages/cli/src/commands/database/seed/index.ts | 📈 +1.13 KB |
| packages/cli/src/commands/database/seed/tables.ts | 📈 +3.28 KB |
| packages/cli/src/commands/database/seed/utils.ts | 📈 +1.56 KB |
| packages/cli/src/commands/install/utils.ts | 📈 +201 Bytes |
| packages/core/src/libraries/id-format.test.ts | 📈 +7.42 KB |
| packages/core/src/libraries/id-format.ts | 📈 +3.51 KB |
| packages/core/src/libraries/user.ts | 📈 +223 Bytes |
| packages/core/src/queries/tenant-id-config.test.ts | 📈 +3.14 KB |
| packages/core/src/queries/tenant-id-config.ts | 📈 +1.62 KB |
| packages/core/src/routes/applications/application.ts | 📈 +30 Bytes |
| packages/core/src/routes/organization-role/index.ts | 📈 +58 Bytes |
| packages/core/src/routes/organization/index.ts | 📈 +76 Bytes |
| packages/core/src/routes/role.ts | 📈 +27 Bytes |
| packages/core/src/routes/saml-application/index.ts | 📈 +18 Bytes |
| packages/core/src/tenants/Libraries.ts | 📈 +151 Bytes |
| packages/core/src/tenants/Queries.ts | 📈 +135 Bytes |
| packages/core/src/utils/SchemaRouter.ts | 📈 +490 Bytes |
| packages/schemas/alterations/next-1762400000.1-add-uuid-support-tenant-config.ts | 📈 +3.06 KB |
| packages/schemas/alterations/next-1762400000.2-add-uuid-support-primary-tables.ts | 📈 +2.07 KB |
| packages/schemas/alterations/next-1762400000.3-add-uuid-support-user-fks.ts | |
| packages/schemas/alterations/next-1762400000.4-add-uuid-support-org-role-fks.ts | |
| packages/schemas/alterations/next-1762400000.5-add-uuid-support-app-fks.ts | |
| packages/schemas/src/seeds/index.ts | 📈 +39 Bytes |
| packages/schemas/src/seeds/tenant-id-config.ts | 📈 +705 Bytes |
| packages/schemas/tables/application_secrets.sql | 0 Bytes |
| packages/schemas/tables/application_sign_in_experiences.sql | 0 Bytes |
| packages/schemas/tables/application_user_consent_organization_resource_scopes.sql | 0 Bytes |
| packages/schemas/tables/application_user_consent_organization_scopes.sql | 0 Bytes |
| packages/schemas/tables/application_user_consent_organizations.sql | 0 Bytes |
| packages/schemas/tables/application_user_consent_resource_scopes.sql | 0 Bytes |
| packages/schemas/tables/application_user_consent_user_scopes.sql | 0 Bytes |
| packages/schemas/tables/applications.sql | 0 Bytes |
| packages/schemas/tables/applications_roles.sql | 0 Bytes |
| packages/schemas/tables/daily_active_users.sql | 0 Bytes |
| packages/schemas/tables/organization_application_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_invitation_role_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_invitations.sql | 0 Bytes |
| packages/schemas/tables/organization_jit_email_domains.sql | 0 Bytes |
| packages/schemas/tables/organization_jit_roles.sql | 0 Bytes |
| packages/schemas/tables/organization_jit_sso_connectors.sql | 0 Bytes |
| packages/schemas/tables/organization_role_application_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_role_resource_scope_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_role_scope_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_role_user_relations.sql | 0 Bytes |
| packages/schemas/tables/organization_roles.sql | 0 Bytes |
| packages/schemas/tables/organization_user_relations.sql | 0 Bytes |
| packages/schemas/tables/organizations.sql | 0 Bytes |
| packages/schemas/tables/personal_access_tokens.sql | 0 Bytes |
| packages/schemas/tables/roles.sql | 0 Bytes |
| packages/schemas/tables/roles_scopes.sql | 0 Bytes |
| packages/schemas/tables/saml_application_configs.sql | 0 Bytes |
| packages/schemas/tables/saml_application_secrets.sql | 0 Bytes |
| packages/schemas/tables/saml_application_sessions.sql | 0 Bytes |
| packages/schemas/tables/secrets.sql | 0 Bytes |
| packages/schemas/tables/sso_connector_idp_initiated_auth_configs.sql | 0 Bytes |
| packages/schemas/tables/subject_tokens.sql | 0 Bytes |
| packages/schemas/tables/tenant_id_config.sql | 📈 +608 Bytes |
| packages/schemas/tables/user_sso_identities.sql | 0 Bytes |
| packages/schemas/tables/users.sql | 0 Bytes |
| packages/schemas/tables/users_roles.sql | 0 Bytes |
| packages/schemas/tables/verification_records.sql | 0 Bytes |
| packages/schemas/tables/verification_statuses.sql | 0 Bytes |
| packages/shared/package.json | 📈 +23 Bytes |
| packages/shared/src/node/env/GlobalValues.ts | 📈 +335 Bytes |
| packages/shared/src/utils/id.test.ts | 📈 +1.85 KB |
| packages/shared/src/utils/id.ts | 📈 +1.11 KB |
| pnpm-lock.yaml | 📈 +349 Bytes |
|
I created this feature because it's the only blocker for us to use logto in our environment. We use UUIDs across our rest APIs. Implementing nanoid would require mapping nanoid to uuid and it feels like a hacky solution. PostgreSQL 18 will also have improved UUIDv7 support: https://www.thenile.dev/blog/uuidv7 Backwards compatible and selectable if you prefer to use nanoid. Let me know what you think. |
|
@Zyles We’re also planning to upgrade the Postgres version. I’ll get back to you once I have a final answer from the team about this. |
|
Hi @Zyles Thanks for the clear write-up, the idea makes sense. If you need it, forking and extending might be the better path. Appreciate the contribution! 🙌 |
I would prefer not having to fork and patch. What type of isolation do you have problems with? I could make it so that this is only applicable on new deployments, so you will need to explicitly set the ID generation on project installation and it will migrate either varchar or UUID for the column. This will keep the old varchar lengths vs UUID type in DB. Nothing really changes in currently running projects. |
|
This pattern also opens up for using other ID generation libraries if someone else is using something of the 20+ libraries out there since you are just working against one function (generateId). |
|
Hi @Zyles, if the following conditions are met, we can accept this PR:
|
|
This PR is stale because it has been open for 30 days with no activity. |
|
Hi, @Zyles any updates on this? |
I will look at it in February. |
|
@wangsijie How do you envision the ENV variable? This current solution makes it so that each tenant can have their own config/ID generation method. An ENV variable would force all tenants on the installation to use the same ID generation method? |
I think this should be instance-level control |
feat: add UUID v7 support for entity IDs with per-tenant configuration
Add support for UUID v7 as an alternative ID format, configurable per tenant.
This allows tenants to choose between nanoid (existing default) and UUID v7 for
better compatibility with external systems and time-ordered ID requirements.
All entity ID columns expanded from varchar(12/21) to varchar(36) to
accommodate UUID v7 format. Existing nanoid IDs continue to work without migration.
PostgreSQL 18 will have improved support for UUID v7 natively using UUID column type allowing for faster indexing since UUID v7 is time-ordered.
Key Changes
Database Schema (packages/schemas)
tenant_id_configtable with unifiedid_formatcolumnCore Libraries (packages/core)
id-formatlibrary for tenant-specific ID format managementtenant-id-configqueries for configuration persistenceShared Utilities (packages/shared)
uuidpackagegenerateUuidV7()andgenerateId(format, size?)functionsIdFormattype: 'nanoid' | 'uuidv7'DEFAULT_ID_FORMATenvironment variable (defaults to 'nanoid')