April 2026
All articlesBubble Unique IDs are not UUIDs. They are system-generated strings, and that matters when deciding how to migrate them or reproduce the same format when leaving Bubble.
Bubble Unique ID structure, and how to replicate it in your codebase.
Bubble's default Unique ID is not a UUID.
It is a system-generated string created automatically when the object is created. In practice, it usually follows a structure like:
[timestamp of creation]x[random sequence]For example, if you create a new entry at Jan 16, 2026 11:24 pm, its Unix timestamp equivalent is 1768605889312, so the Unique ID could be:
1768605889312x600101118159717500So every entry in your Bubble database automatically includes this default Unique ID, which acts as the main identifier for that thing.
Bubble's Unique ID is not a UUID field. Because of that, in a migration to Postgres, the closest equivalent is usually to store it as TEXT, and use it as the primary key.
This is usually the right choice, because it preserves all references exactly as they existed in Bubble. If other rows point to that ID, they can keep pointing to the same value after migration.
In case you want to start using automatically generated UUIDs, this will add some risk and complexity to the migration.
What we recommend is a progressive approach, in which you create your new UUID column as primary key, but keep your Bubble unique ID intact for compatibility during the migration. Remember that your foreign keys will still be pointing to Bubble unique IDs, so you will need to update them to reference the new primary key, as new rows will not have this column.
If you need or want to keep using this same structure after migrating out of Bubble, then you should create your own function that generates IDs in a similar format.
For Supabase/Postgres, run this once to create the generator function:
create or replace function public.generate_bubble_like_id()
returns text
language sql
volatile
as $$
select
floor(extract(epoch from clock_timestamp()) * 1000)::bigint::text
|| 'x' ||
lpad(
floor(random() * 1000000000000000000)::bigint::text,
18,
'0'
);
$$;Then, for each table where you want Bubble-like IDs on id, set the default like this:
alter table public.your_table
alter column id set default public.generate_bubble_like_id();Now, each time you create a new row, this will mimic Bubble's internal ID generator logic: a timestamp-like prefix followed by a long random numeric suffix.
Self-serve tools or a done-for-you service. Your app stays live while we move everything.