Skip to content

feat: add UUID support#7962

Open
Zyles wants to merge 1 commit into
logto-io:masterfrom
Zyles:feat/uuid-support
Open

feat: add UUID support#7962
Zyles wants to merge 1 commit into
logto-io:masterfrom
Zyles:feat/uuid-support

Conversation

@Zyles
Copy link
Copy Markdown

@Zyles Zyles commented Nov 11, 2025

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)

  • Add tenant_id_config table with unified id_format column
  • Expand all entity ID columns to varchar(36):
    • Primary tables: users, organizations, roles, organization_roles, applications
    • 40+ foreign key columns across related tables

Core Libraries (packages/core)

  • Add id-format library for tenant-specific ID format management
    • Multi-level caching (in-memory + Redis) for performance
    • Automatic fallback to environment variable defaults
  • Add tenant-id-config queries for configuration persistence
  • Update entity creation routes to use configured ID format:
    • Users, organizations, roles, organization roles, applications
  • Integrate ID format library into tenant context

Shared Utilities (packages/shared)

  • Add UUID v7 generation support via uuid package
  • Add generateUuidV7() and generateId(format, size?) functions
  • Add IdFormat type: 'nanoid' | 'uuidv7'
  • Add DEFAULT_ID_FORMAT environment variable (defaults to 'nanoid')
  • Consolidate from 4 separate format env vars to single unified setting

@github-actions github-actions Bot added the feature Cool stuff label Nov 11, 2025
@github-actions
Copy link
Copy Markdown

COMPARE TO master

Total Size Diff ⚠️ 📈 +69.42 KB

Diff by File
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 ⚠️ 📈 +10.89 KB
packages/schemas/alterations/next-1762400000.4-add-uuid-support-org-role-fks.ts ⚠️ 📈 +14.98 KB
packages/schemas/alterations/next-1762400000.5-add-uuid-support-app-fks.ts ⚠️ 📈 +10.45 KB
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

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Nov 11, 2025

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.

@wangsijie
Copy link
Copy Markdown
Contributor

@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.

@wangsijie
Copy link
Copy Markdown
Contributor

Hi @Zyles

Thanks for the clear write-up, the idea makes sense.
But merging it would change the data structure and can’t be fully isolated, so it doesn’t fit our roadmap.

If you need it, forking and extending might be the better path.

Appreciate the contribution! 🙌

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Nov 25, 2025

Hi @Zyles

Thanks for the clear write-up, the idea makes sense. But merging it would change the data structure and can’t be fully isolated, so it doesn’t fit our roadmap.

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.

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Nov 26, 2025

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).

@wangsijie
Copy link
Copy Markdown
Contributor

Hi @Zyles, if the following conditions are met, we can accept this PR:

  1. The feature is controlled via environment variables.
  2. There is no impact on instances where this feature is disabled at the database level. For example, this can be enforced during database seeding, and once set, users should not be able to modify this behavior afterward.

@github-actions
Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale label Jan 20, 2026
@wangsijie
Copy link
Copy Markdown
Contributor

Hi, @Zyles any updates on this?

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Jan 21, 2026

Hi, @Zyles any updates on this?

I will look at it in February.

@github-actions github-actions Bot removed the stale label Jan 22, 2026
@Zyles
Copy link
Copy Markdown
Author

Zyles commented Feb 8, 2026

@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?

@wangsijie
Copy link
Copy Markdown
Contributor

@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

@Zyles Zyles force-pushed the feat/uuid-support branch from 9ce81e6 to c80788e Compare February 25, 2026 15:20
@github-actions github-actions Bot added size/xl and removed size/xl labels Feb 25, 2026
@Zyles Zyles force-pushed the feat/uuid-support branch 2 times, most recently from ae19d73 to 8396c38 Compare February 25, 2026 15:38
@github-actions github-actions Bot added size/xl and removed size/xl labels Feb 25, 2026
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 11, 2026
@Zyles Zyles force-pushed the feat/uuid-support branch from 1acad7a to 25c00a1 Compare March 11, 2026 17:15
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 11, 2026
@Zyles
Copy link
Copy Markdown
Author

Zyles commented Mar 11, 2026

@wangsijie Check this out. Did a bunch of refactoring and better type support.

The flow is now:

  • If you use ENV ID_FORMAT you will bypass the id format question in npx logto db seed, this allows you to auto setup in prod
  • Saves id format in systems table, if you restart without ENV variable it will just go with that setting
  • If you change ID_FORMAT on already installed it will error

@wangsijie
Copy link
Copy Markdown
Contributor

Hi, @Zyles, thanks for the contribution, it looks good to me, and now the team is reviewing this PR, let's wait for a short time

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an instance-wide, configurable entity ID format (default nanoid, optional UUID v7), updates shared ID utilities, database table definitions, seed flows, and runtime preconditions to support format-aware IDs and persistent ID-format locking via the systems table.

Changes:

  • Introduce IdFormat + format-aware ID generation (UUID v7) and seed-ID conversion utilities in @logto/shared.
  • Update schema SQL to use an ${id_format} placeholder for entity ID columns and adjust schema/type generation to recognize and validate those columns.
  • Extend CLI install/seed flows to select/store ID_FORMAT, resolve ${id_format} at seed time, and validate env-vs-db format at runtime startup.

Reviewed changes

Copilot reviewed 79 out of 80 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds uuid dependency resolution and lock updates.
packages/shared/package.json Adds uuid dependency to shared package.
packages/shared/src/utils/id.ts Adds IdFormat, UUID v7 generation, seed ID conversion, and format-aware generateId/generateStandardId.
packages/shared/src/utils/id.test.ts Adds tests for UUID v7 and format-aware generateId.
packages/shared/src/node/env/GlobalValues.ts Adds idFormat env parsing/validation to global env values.
packages/schemas/tables/verification_statuses.sql Switches ID columns to ${id_format}.
packages/schemas/tables/verification_records.sql Switches ID columns to ${id_format}.
packages/schemas/tables/users.sql Switches users.id to ${id_format} and widens application_id to varchar(36).
packages/schemas/tables/users_roles.sql Switches join IDs to ${id_format}.
packages/schemas/tables/user_sso_identities.sql Switches IDs to ${id_format}.
packages/schemas/tables/subject_tokens.sql Switches user_id to ${id_format}.
packages/schemas/tables/sso_connector_idp_initiated_auth_configs.sql Widens default_application_id to varchar(36).
packages/schemas/tables/service_logs.sql Switches id to ${id_format}.
packages/schemas/tables/sentinel_activities.sql Switches id to ${id_format}.
packages/schemas/tables/secrets.sql Switches IDs to ${id_format}.
packages/schemas/tables/secret_social_connector_relations.sql Switches secret_id to ${id_format}.
packages/schemas/tables/secret_enterprise_sso_connector_relations.sql Switches secret_id to ${id_format}.
packages/schemas/tables/scopes.sql Widens id/resource_id to varchar(36).
packages/schemas/tables/saml_application_sessions.sql Widens application_id to varchar(36).
packages/schemas/tables/saml_application_secrets.sql Switches secret id to ${id_format}; widens application_id.
packages/schemas/tables/saml_application_configs.sql Widens application_id to varchar(36).
packages/schemas/tables/roles.sql Switches roles.id and function arg types to ${id_format}.
packages/schemas/tables/roles_scopes.sql Switches IDs to ${id_format}; widens scope_id to varchar(36).
packages/schemas/tables/resources.sql Widens resources.id to varchar(36).
packages/schemas/tables/personal_access_tokens.sql Switches user_id to ${id_format}.
packages/schemas/tables/passcodes.sql Switches id to ${id_format}.
packages/schemas/tables/organizations.sql Switches organizations.id to ${id_format}.
packages/schemas/tables/organization_user_relations.sql Switches org/user IDs to ${id_format}.
packages/schemas/tables/organization_scopes.sql Widens id to varchar(36).
packages/schemas/tables/organization_roles.sql Switches id and function arg types to ${id_format}.
packages/schemas/tables/organization_role_user_relations.sql Switches org/role/user IDs to ${id_format}.
packages/schemas/tables/organization_role_scope_relations.sql Switches organization_role_id to ${id_format}; widens scope IDs.
packages/schemas/tables/organization_role_resource_scope_relations.sql Switches organization_role_id to ${id_format}; widens scope IDs.
packages/schemas/tables/organization_role_application_relations.sql Switches org/role IDs to ${id_format}; widens application_id.
packages/schemas/tables/organization_jit_sso_connectors.sql Switches organization_id to ${id_format}.
packages/schemas/tables/organization_jit_roles.sql Switches org/role IDs to ${id_format}.
packages/schemas/tables/organization_jit_email_domains.sql Switches organization_id to ${id_format}.
packages/schemas/tables/organization_invitations.sql Switches invitation/org/user IDs to ${id_format}.
packages/schemas/tables/organization_invitation_role_relations.sql Switches IDs to ${id_format}.
packages/schemas/tables/organization_application_relations.sql Switches organization_id to ${id_format}; widens application_id.
packages/schemas/tables/one_time_tokens.sql Switches id to ${id_format}.
packages/schemas/tables/oidc_session_extensions.sql Switches account_id to ${id_format}.
packages/schemas/tables/logs.sql Switches id to ${id_format}.
packages/schemas/tables/idp_initiated_saml_sso_sessions.sql Switches id to ${id_format}.
packages/schemas/tables/hooks.sql Switches id to ${id_format}.
packages/schemas/tables/email_templates.sql Switches id to ${id_format}.
packages/schemas/tables/domains.sql Switches id to ${id_format}.
packages/schemas/tables/daily_token_usage.sql Switches id to ${id_format}.
packages/schemas/tables/daily_active_users.sql Switches IDs to ${id_format}.
packages/schemas/tables/custom_profile_fields.sql Switches id to ${id_format}.
packages/schemas/tables/custom_phrases.sql Switches id to ${id_format}.
packages/schemas/tables/applications.sql Widens applications.id and related function arg types to varchar(36).
packages/schemas/tables/applications_roles.sql Switches join IDs to ${id_format}; widens application_id.
packages/schemas/tables/application_user_consent_user_scopes.sql Widens application_id to varchar(36).
packages/schemas/tables/application_user_consent_resource_scopes.sql Widens application_id/scope_id to varchar(36).
packages/schemas/tables/application_user_consent_organizations.sql Widens application_id; switches org/user IDs to ${id_format}.
packages/schemas/tables/application_user_consent_organization_scopes.sql Widens application_id/organization_scope_id to varchar(36).
packages/schemas/tables/application_user_consent_organization_resource_scopes.sql Widens application_id/scope_id to varchar(36).
packages/schemas/tables/application_sign_in_experiences.sql Widens application_id to varchar(36).
packages/schemas/tables/application_secrets.sql Widens application_id to varchar(36).
packages/schemas/tables/_after_all.sql Adds grant usage on schema public for tenant role after schema creation.
packages/schemas/src/types/tenant-organization.ts Uses buildSeedId() for tenant-organization IDs and tenant role IDs.
packages/schemas/src/types/system.ts Adds systems.idFormat key + guard/types for persisted ID format.
packages/schemas/src/types/mapi-proxy.ts Makes proxy role/app IDs format-aware via buildSeedId().
packages/schemas/src/seeds/management-api.ts Adds createDefaultManagementApi() to generate format-aware seed data.
packages/schemas/src/seeds/application.ts Adds format-aware getters for built-in application IDs and adjusts built-in logic.
packages/schemas/src/gen/utils.ts Marks ${id_format} columns via /* @id_format */ during parsing.
packages/schemas/src/gen/types.ts Adds Field.isIdFormat flag for schema generation.
packages/schemas/src/gen/schema.ts Widens max length validations for ${id_format} columns (up to 36).
packages/schemas/src/gen/index.ts Replaces ${id_format} with annotated default during type generation.
packages/core/src/utils/SchemaRouter.ts Notes idLength is ignored for UUID format; refactors ID assignment.
packages/core/src/routes/organization-role/index.ts Minor refactor of role insert call formatting.
packages/core/src/oidc/adapter.ts Builds Admin Console metadata at runtime; uses format-aware built-in client IDs.
packages/core/src/libraries/user.ts Switches user ID generation from short nanoid to format-aware standard IDs.
packages/core/src/env-set/preconditions.ts Adds startup check to enforce env-vs-db idFormat consistency (and adopt DB value when env unset).
packages/console/src/containers/ConsoleContent/hooks.ts Skips tenant-scope listening for OSS (cloud-only behavior).
packages/cli/src/commands/install/utils.ts Adds ID format validation/prompt before seeding during install.
packages/cli/src/commands/database/seed/utils.ts Adds interactive prompt for choosing ID format.
packages/cli/src/commands/database/seed/tables.ts Resolves ${id_format} in SQL at seed-time; persists chosen format in systems.
packages/cli/src/commands/database/seed/index.ts Adds --id-format option and resolves ID_FORMAT (CLI/env/prompt/default).
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

packages/schemas/src/types/tenant-organization.ts:27

  • getTenantOrganizationId() now returns buildSeedId('t-${tenantId}'), which becomes a UUID v5 when ID_FORMAT=uuid. In that mode, getTenantIdFromOrganizationId() will always throw because UUIDs don’t start with t-, breaking tenant navigation/mapping (e.g. Console uses getTenantIdFromOrganizationId(organizationId)). Consider keeping tenant-organization IDs reversible (e.g. store tenantId separately and stop parsing it from organizationId, or avoid UUID conversion for this specific derived ID scheme).
export const getTenantOrganizationId = (tenantId: string) => buildSeedId(`t-${tenantId}`);

/** Given an admin tenant organization ID, check the format and return the corresponding user tenant ID. */
export const getTenantIdFromOrganizationId = (organizationId: string) => {
  if (!organizationId.startsWith('t-')) {
    throw new Error(`Invalid admin tenant organization ID: ${organizationId}`);
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/core/src/env-set/preconditions.ts Outdated
Comment thread packages/cli/src/commands/database/seed/tables.ts
Comment thread packages/cli/src/commands/database/seed/tables.ts
Comment thread packages/schemas/src/seeds/application.ts Outdated
Comment thread packages/shared/src/utils/id.ts
@Zyles Zyles force-pushed the feat/uuid-support branch from 25c00a1 to 2c0c598 Compare March 12, 2026 09:50
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 12, 2026
@Zyles Zyles force-pushed the feat/uuid-support branch from 2c0c598 to 7a662db Compare March 19, 2026 09:48
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 19, 2026
@Zyles
Copy link
Copy Markdown
Author

Zyles commented Mar 19, 2026

@wangsijie The copilot issues have been resolved.

Add support for UUID v7 as an alternative ID format, configurable per tenant.
@Zyles Zyles force-pushed the feat/uuid-support branch from 7a662db to e71e906 Compare March 19, 2026 10:20
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 19, 2026
@Zyles Zyles changed the title feat: add UUID v7 support feat: add UUID support Mar 19, 2026
@github-actions github-actions Bot added size/xl and removed size/xl labels Mar 19, 2026
@wangsijie
Copy link
Copy Markdown
Contributor

There are new conflicts

@simeng-li
Copy link
Copy Markdown
Contributor

Hi @Zyles

First of all, thank you so much for your hard work on this PR. We really appreciate the effort and thought you put into it. Also, apologies for the delayed response, as we took some time to review the changes internally with the team.

After reviewing, we feel that while the UUID v7 support is a valuable direction, the current implementation mainly targets newly provisioned Logto open-source instances. For existing systems, it introduces certain migration risks and additional validation effort.

Mostly, the current approach requires fairly intrusive changes to the existing schema/table definitions, which could increase long-term maintenance costs for future development. Especially given the fact that we may introduce new table definitions and DB alterations frequently. Given these considerations, we don’t think this implementation is suitable for merging into the main branch at the moment.

That said, we do agree with the overall goal of supporting newer UUID formats. It’s just that, considering the balance between backward compatibility, maintenance overhead, and migration impact, this particular approach may not be the best fit.

As a potential direction, it might be worth exploring a less intrusive approach, for example, introducing a post-create / post-alter table hook or function in the seeding and alteration script. With the env feature flag you have introduced, this could automatically apply UUID-related changes during seed jobs or after schema updates. This would help minimize changes to existing schema definitions while limiting the impact scope to newly initialized systems.

Thanks again for the contribution. We really appreciate it, and we’d be happy to continue discussing alternative approaches if you’re interested.

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Mar 20, 2026

Hi @Zyles

First of all, thank you so much for your hard work on this PR. We really appreciate the effort and thought you put into it. Also, apologies for the delayed response, as we took some time to review the changes internally with the team.

After reviewing, we feel that while the UUID v7 support is a valuable direction, the current implementation mainly targets newly provisioned Logto open-source instances. For existing systems, it introduces certain migration risks and additional validation effort.

Mostly, the current approach requires fairly intrusive changes to the existing schema/table definitions, which could increase long-term maintenance costs for future development. Especially given the fact that we may introduce new table definitions and DB alterations frequently. Given these considerations, we don’t think this implementation is suitable for merging into the main branch at the moment.

That said, we do agree with the overall goal of supporting newer UUID formats. It’s just that, considering the balance between backward compatibility, maintenance overhead, and migration impact, this particular approach may not be the best fit.

As a potential direction, it might be worth exploring a less intrusive approach, for example, introducing a post-create / post-alter table hook or function in the seeding and alteration script. With the env feature flag you have introduced, this could automatically apply UUID-related changes during seed jobs or after schema updates. This would help minimize changes to existing schema definitions while limiting the impact scope to newly initialized systems.

Thanks again for the contribution. We really appreciate it, and we’d be happy to continue discussing alternative approaches if you’re interested.

Okay, that is disappointing to hear. The solution is working and I have tested every possible scenario I came up with.

The pattern follows the same pattern you already use in other SQL files with the variable tokens.

I don't think I can come up with a cleaner solution than this.

If you want to do post alteration that would require maintaining an array of tables that need to be updated instead and rely on matching the correct columns? How do you envision this to work?

If you are worried by introducing a new id or foreign keys in new migration files that is not compatible you could have a git hook or similar that analyze the new migration SQL, to determine if ${id_format} is missing and error out before it is checked into the project to enforce the pattern.

What is a realistic solution for you?

@simeng-li
Copy link
Copy Markdown
Contributor

You’re right that post-table-creation transformation is relatively straightforward, but post-alteration handling is much harder. In practice, it’s difficult to make ID-format conversion fully automatic and reliable for all future alteration scripts.

We truly appreciate your contribution. If you’d like, please feel free to keep a fork with UUID support (or your own variant), or leave this PR open as a reference for future exploration. Suggestions are always welcome, and we’ll keep you posted if we come up with a better path forward.

@Zyles
Copy link
Copy Markdown
Author

Zyles commented Apr 6, 2026

I will just drop this in here: https://better-auth.com/docs/reference/options#advanced

This platform supports custom id generation and defaults with serial and uuid.

I still think this would benefit this platform greatly.

We opt-ed out to use your cloud offering because of nanoid. If you had uuid support in the cloud we would have already been a customer. This was a hard rule in our decision to not having to map new auth id numbers to our current infrastructure.

@simeng-li
Copy link
Copy Markdown
Contributor

Quick updates, we have added this to our Postgres DB updates project, and will address it by then. Thanks again for your great effort. I'll leave this PR open for future reference, until this issue has been addressed in Logto code base.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants