February 2026
All articlesBubble geographic address fields are not plain strings. They contain structured location data, which matters when deciding how to migrate them into Postgres.
When you save a Geographic Address in your Bubble database, it is not just storing a plain string. Behind the scenes, Bubble integrates with Google's Places API and Geocoding API to store locations as rich structured data. That is what actually allows all the rich operations such as distance calculations, map integrations, and location extraction.
In practice, it stores structured location data:
Example response from the Data API:
{
"address": "510 E 13th St, New York, NY 10009, USA",
"lat": 40.7293034,
"lng": -73.9803629
}To make the rest of the article easier to follow, imagine you have a Bubble data type called restaurants with these fields:
| Field | Bubble type |
|---|---|
id | id |
name | text |
address | geographic address |
The most important part is understanding that a standard Postgres database does not have a direct equivalent to Bubble's geographic address type.
Because of that, the most straightforward way to store these addresses is as a JSON or JSONB column, which matches how the data is effectively returned in the Data API. So, in the restaurants example above:
address could be stored as JSONB or JSONCREATE TABLE restaurants (
id UUID PRIMARY KEY,
name TEXT,
address JSONB
);However, the approach we usually recomend is to create a new table called geographic_addresses that stores all the components that appear in the JSON as separate columns, and then reference those rows as a foreign key from your original table.
In this scenario, we would create these tables:
CREATE TABLE restaurants (
id UUID PRIMARY KEY,
name TEXT,
address_id UUID REFERENCES geographic_addresses(id)
);CREATE TABLE geographic_addresses (
id UUID PRIMARY KEY,
address TEXT,
lat DOUBLE PRECISION,
lng DOUBLE PRECISION
);Then your restaurants table could reference one row from that table for its address.
While this adds some migration complexity, it helps with performance in case you constantly need to parse a JSON object. Instead, you reference a table and can read the matching columns directly. It also gives you more flexibility, because you can keep adding new columns that may be relevant for geographic addresses, such as ZIP code, city, country, and other fields you may want to store separately.
Self-serve tools or a done-for-you service. Your app stays live while we move everything.