> For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://manual.bubble.io/help-guides/data/the-database/data-types-and-fields.md).

# Data types and fields

{% hint style="info" %}
We also have multiple guides on how to set up your database structure based on what kind of app you are building. You can take a look at these in our article series on *Database structure by app type*.

Article series: [Database structure by app type](/help-guides/data/the-database/database-structure-by-app-type.md)

You may also be interested in our introductory guide to planning your database structure:

Article: [Database structure](/help-guides/getting-started/building-your-first-app/database-structure.md)
{% endhint %}

Every database in Bubble is built from two basic building blocks: data types and fields. A data type defines what kind of thing you're storing, like a user, a product, or a blog post. A field defines a specific piece of information that thing holds, like a name, a price, or a publish date. This article covers how to create and work with both.

## What are data types and fields?

The database consists of different **data types** that you, as the developer, plan and set up. Data types are like containers that hold a specific kind of information, and each data type is made up of **fields**, where that information is actually stored.

If you were building a phone book, the data type would be *Contact*, and its fields would be *Name*, *Email address*, and *Phone number*. In a sports league management app, one data type might hold information about teams, such as their name, coach, and roster of players, while another data type holds information about games, such as the date, location, and final score.

With Bubble's visual editor, you have complete freedom to structure, manage, and connect data types however your app needs.

## Creating a data type

You can create up to 1,000 custom data types.

{% stepper %}
{% step %}

#### Open the Data tab

Navigate to the **Data** tab in the Bubble editor.
{% endstep %}

{% step %}

#### Open Data types

Go to the **Data types** section.
{% endstep %}

{% step %}

#### Name your data type

In the field labeled *New type*, enter a name. You can change this later at any time.
{% endstep %}

{% step %}

#### Create it

Click **Create**. Your new data type appears in the *Custom data types* list.
{% endstep %}
{% endstepper %}

### Naming data types

Bubble lets you name your data types however you like, even using spaces. That said, a couple of guidelines help keep things manageable:

* **Use unique names.** Bubble does support duplicate names, but giving your data types unique names makes it easier to identify the right one. This also affects option sets, since option sets and data types often show up in the same lists.
* **Use singular names.** Bubble automatically pluralizes names. For example, if you name your data type *Event*, Bubble refers to it as *Events* wherever that's appropriate.

<details>

<summary><mark style="color:blue;">Video lessons</mark></summary>

* [Naming your data types and fields](https://www.youtube.com/watch?v=XueeVCReuI8)

</details>

## Fields

{% hint style="warning" %}
Deleting a field has some security implications you should know about. See the [expandable box](#important-information-when-deleting-fields-1) below for details.
{% endhint %}

Each data type consists of fields that hold different kinds of information. A field is formatted in a specific way and can only hold the type of information it's set up to contain. In a phone book, for example, a *Contact* has fields for name, date of birth, and email address, and those formats stay constant: name and email address always contain text, and date of birth always contains a date. The field is where that information is actually stored.

### Field types

Bubble has the following built-in field types:

<table><thead><tr><th width="199.09375">Field type</th><th>Description</th></tr></thead><tbody><tr><td>text</td><td>A string of text that can contain any kind of character.</td></tr><tr><td>number</td><td>A numerical value, which can be a whole number or a decimal. Bubble formats numbers in US standard format, using a period (.) to separate the integer part from the fractional part (e.g., 1234.56).</td></tr><tr><td>numeric range</td><td>A range consisting of a low and a high value, such as 5-10.</td></tr><tr><td>date</td><td>Contains a date and time.</td></tr><tr><td>date range</td><td>A range of dates, such as 1/1/1970 - 1/15/1970.</td></tr><tr><td>date interval</td><td>The difference between two dates, expressed as milliseconds.</td></tr><tr><td>yes / no</td><td>A value that can be true or false (sometimes called a boolean).</td></tr><tr><td>file</td><td>The URL of a file.</td></tr><tr><td>image</td><td>The URL of an image file.</td></tr><tr><td>geographic address</td><td>A Google Maps formatted address.</td></tr><tr><td>data type <mark style="color:$info;">(see</mark> <a href="#using-a-data-type-as-a-field-type"><mark style="color:$info;">below</mark></a><mark style="color:$info;">)</mark></td><td>Any data type you set up can also be used as a field type.</td></tr></tbody></table>

### Using a data type as a field type

The last row in the table above is particularly significant: every data type you create can be used to format a field on a different data type, which is how you connect them to each other. This is where the flexibility of Bubble's database becomes apparent. By creating custom data types and populating them with custom fields, you can structure your database for almost any scenario.

For example, say you have a data type called *Blog post*, and you want each post to have an *Author*. You'd set up a field called *Author* on the *Blog post* data type and set its type to *User*, directly connecting a user to the blog post.

The same approach works for connecting other data types. For instance, you could create a field called *Products* on a *Cart* data type, check *This field is a list*, and choose *Product* as the field type, letting a cart hold multiple products.

### Storing a list of values

Any field can also be set up to store a *list* of values instead of just one. For example, if you want to store more than one text value, check the box labeled *This field is a list (multiple entries)*. This lets you add several values that make up a list, such as Red, Blue, Green, and Yellow.

Any field type can hold a list, including custom data types. This lets you reference multiple things at once, such as the tags connected to a blog post or the products in a cart.

<details>

<summary><mark style="color:blue;">Video lessons</mark></summary>

* [How to create a field as a list](https://www.youtube.com/watch?v=w2xJ_RhAfMk)

</details>

### Built-in fields

In addition to the fields you choose to add, Bubble automatically sets up the following fields on every data type:

#### Unique ID

The *Unique ID* is a 32-character alphanumeric string that identifies one specific thing in your database. It's generated automatically when the thing is created, and it can't be edited. A unique ID (sometimes shortened to UID) looks like this: `1651238619517x600101118159717500`.

#### Date created and date modified

These two fields are also populated automatically by Bubble, and both are stored in the *date* format. The *Date created* field never changes, while the *Date modified* field updates automatically any time changes are made to the thing.

You cannot make changes to any of these fields, as they are the 'source of truth' for when a record was created and last modified.

#### Slug

The *Slug* field lets you set up a user-friendly, search-engine-optimized URL for a thing. When you [load data onto a page](#user-content-fn-1)[^1], you can tell Bubble to use this text as the last part of the page's URL, giving each thing a unique URL.

For example, if a *Product*'s name is "A Beginner's Guide to Bubble," its slug might be "a-beginners-guide-to-bubble." The slug is then appended to the page URL, like this:

```url
https://www.myapp.com/products/a-beginners-guide-to-bubble
```

This lets you set up friendly, search-engine-optimized URLs for content like articles, blog posts, and products.

You can't change a thing's slug with the [*Make changes to a thing*](#user-content-fn-2)[^2] action. Use the [*Set a thing's slug*](#user-content-fn-3)[^3] action instead.

<details>

<summary><mark style="color:blue;">Video lessons</mark></summary>

* [How to add a data type as a custom field](https://youtu.be/4txlG9nwr1E)

</details>

## Creating a field

Once you've created a data type, you can set up the fields it needs.

{% stepper %}
{% step %}

#### Select the data type

Select the data type you want to add a field to (in this example, *Blog post*).
{% endstep %}

{% step %}

#### Create a new field

Click **Create a new field** at the bottom of the existing fields.
{% endstep %}

{% step %}

#### Name the field

Give the field a fitting name, such as *Author.*
{% endstep %}

{% step %}

#### Choose the field type

Choose the type of data you want to store, either from the built-in types above or from your existing data types. In this example, we selected *User*, since we want the author of the post to be a registered user.
{% endstep %}

{% step %}

#### Choose single or list

Decide whether the field should hold a single item or a *list*. Here, each post should have just one author, so we leave the list box unchecked.
{% endstep %}
{% endstepper %}

## Examples

The examples below show how data types and fields might be set up for a few different kinds of apps. They're not meant as a blueprint or best practice for these categories, just a demonstration of how versatile data types can be.

### Data types

#### Example 1: E-commerce store

An e-commerce store might need three data types to handle basic functionality: *Users* should be able to add *Products* to a *Cart*.

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td><strong>Product</strong></td></tr><tr><td><strong>Cart</strong></td></tr><tr><td><strong>User (built-in)</strong></td></tr></tbody></table>

#### Example 2: Sports league management app

Managing a sports league takes a slightly more complex setup: a league consists of different *Clubs*, each with a few *Teams* made up of *Players*, and the players play *Games*.

The *Player* data type is actually the built-in *User* data type. Since Bubble already provides this data type to let users log in and use the app, it makes sense to reuse it. The *User* data type can't be renamed, so we're simply clarifying that it's referred to as *Player* in this context.

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td><strong>League</strong></td></tr><tr><td><strong>Club</strong></td></tr><tr><td><strong>Team</strong></td></tr><tr><td><strong>Game</strong></td></tr><tr><td><strong>Player (user, built-in)</strong></td></tr></tbody></table>

#### Example 3: Blog

A blog can have a simple setup: blog posts, tags that let you search for posts of a specific type, and authors. Again, the *Author* type is really the *User* type, just labeled to better convey its purpose here.

<table data-view="cards"><thead><tr><th></th></tr></thead><tbody><tr><td><strong>Blog post</strong></td></tr><tr><td><strong>Tags</strong></td></tr><tr><td><strong>Author (user, built-in)</strong></td></tr></tbody></table>

### Adding the fields

#### Example 1: E-commerce store

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Product</strong></td><td>Name (text)<br>Description (text)<br>Image (image)<br>Price (number)</td></tr><tr><td><strong>Cart</strong></td><td>Owner (user)<br>Products (list of Products)</td></tr><tr><td><strong>User (built-in)</strong></td><td>Name</td></tr></tbody></table>

#### Example 2: Sports league management app

This example shows how data types can reference each other down a hierarchy: a player belongs to a team, which belongs to a club, which belongs to a league.

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>League</strong></td><td>Name (text)</td></tr><tr><td><strong>Club</strong></td><td>Name (text)<br>League (League)</td></tr><tr><td><strong>Team</strong></td><td>Name (text)<br>Club (Club)</td></tr><tr><td><strong>Player (user, built-in)</strong></td><td>Name<br>Email (built-in)<br>Team (Team)</td></tr></tbody></table>

#### Example 3: Blog

For the blog, we need blog posts that store a header and post content (both text), the user who wrote it (the author), and a list of tags (such as *Politics* and *Tech*).

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Blog post</strong></td><td>Header (text)<br>Post (text)<br>Author (User)<br>Tags (list of Tags)</td></tr><tr><td><strong>Tag</strong></td><td>Name</td></tr><tr><td><strong>Author (user, built-in)</strong></td><td>Name<br>Email (built-in)</td></tr></tbody></table>

<details>

<summary>Important information when deleting fields</summary>

When you delete a field from a data type, the data stored in that field is **not** automatically removed. The field no longer appears in the editor and can't be used in workflows or design elements, but the underlying data remains in your database and may still be retrievable through API calls or visible in network responses.

This behavior helps preserve the function of any privacy rules that reference the deleted field, even once those references are no longer visible in the editor. Still, there are a few important implications to keep in mind:

**Key points to understand:**

* **Privacy rules still apply.** If a privacy rule previously referenced the field, it's still enforced at runtime, even though it no longer appears in the editor. Since these rules become invisible and uneditable once the field is deleted, we recommend either clearing the field's data beforehand or carefully reviewing your privacy rules to make sure the data stays protected before deletion.
* **The data isn't erased.** Deleting a field only removes it from the editor. The values in that field still exist in the database.
* **The field can still be accessed via API.** API responses (such as through the Data API) may still return the field's values.
* **No WU charge.** Bubble doesn't charge workload units (WU) for data retrieved from deleted fields.
* **Risk of unprotected data.** If no privacy rule currently protects the field, its data could become accessible to unauthorized users through API responses or network activity.
* **App optimization doesn't help here.** The [app optimization](#user-content-fn-4)[^4] feature does not remove this data.

**Best practice:**

Before deleting a field, we recommend the following:

1. **Clear any sensitive data** from the field before deletion, such as through a backend workflow or manual database edit.
2. **Review privacy rules** to understand whether the field is protected, and whether protections need to be adjusted elsewhere.
3. **Test your app and API responses** to make sure no unintended data exposure occurs.

This behavior is designed to avoid silently breaking privacy rules when fields are removed, but it also means you should take extra care when deleting fields that store sensitive information.

</details>

## FAQ: Data types and fields

<details>

<summary>What's the difference between a data type and a field?</summary>

A data type is a category of information, like *User*, *Product*, or *Blog post*. A field is a specific piece of information within that data type, like a name, a price, or a publish date. Think of a data type as a container, and fields as the individual slots inside it that hold your data.

</details>

<details>

<summary>How many data types can I create?</summary>

You can create up to 1,000 custom data types.

</details>

<details>

<summary>Can I rename a data type after I've created it?</summary>

Yes. A data type's name is dynamic, so if you change it, the new name is reflected across your app instantly. There are a few corner cases where a reference to the name may need manual updating, such as dynamic list sorting in searches and lists, or API calls.

</details>

<details>

<summary>Why does Bubble pluralize my data type names?</summary>

Bubble automatically pluralizes data type names wherever that's appropriate. For example, if you name your data type *Event*, Bubble refers to it as *Events* in relevant places. This is why it's best to name your data types in the singular.

</details>

<details>

<summary>Can two data types have the same name?</summary>

Bubble allows duplicate names, but it's best to avoid them. Unique names make it easier to identify the right data type, especially since data types and option sets often appear together in the same lists.

</details>

<details>

<summary>What field types are available?</summary>

Bubble includes text, number, numeric range, date, date range, date interval, yes/no, file, image, geographic address, and any data type you've created. That last one is what lets you connect data types to each other.

See [this table](#field-types) for more info.

</details>

<details>

<summary>Can a field hold more than one value?</summary>

Yes. Check *This field is a list (multiple entries)* on any field to let it store a list of values instead of just one. This works for every field type, including custom data types, so a field can hold a list of things, like the tags on a blog post or the products in a cart.

</details>

<details>

<summary>What fields does Bubble create automatically?</summary>

Every data type automatically gets a *Unique ID*, a *Date created* field, a *Date modified* field, and a *Slug* field. You don't need to set these up yourself, though the slug needs a value assigned to it if you want to use it.

</details>

<details>

<summary>What is the Unique ID used for?</summary>

The Unique ID is a 32-character alphanumeric string that identifies one specific thing in your database. It's generated automatically when the thing is created and can't be edited.

In most cases, you won't refer to it directly, although there may be certain advanced scenarios where you do.

</details>

<details>

<summary>How do I set up a friendly URL for a thing?</summary>

Use the *Slug* field. It lets you assign a search-engine-optimized string, like a blog post title in URL form, that Bubble appends to the end of a page's URL. You'll need to set the slug's value yourself using the [*Set a thing's slug*](/core-resources/bubble-workflows/bubble-actions/database-actions.md#set-a-things-slug) action, since it isn't generated automatically.

</details>

<details>

<summary>Why can't I change a thing's slug with "Make changes to a thing"?</summary>

The slug field is updated through its own action, *Set a thing's slug*, rather than the general-purpose *Make changes to a thing* action. This is because Bubble applies formatting behind the scenes to keep the slug URL-friendly.

</details>

<details>

<summary>What happens to the data if I delete a field?</summary>

The data isn't erased. Deleting a field removes it from the editor, so it can't be used in workflows or design elements, but the underlying values remain in the database and may still be retrievable through API calls or visible in network responses. Any privacy rule that referenced the field also stays in effect, even though the reference is no longer visible in the editor.

</details>

<details>

<summary>Is it safe to delete a field that holds sensitive data?</summary>

Only if you take a few precautions first. Since the data isn't automatically erased, we recommend (in this order):

1. Delete any sensitive data from the field before deletion.
2. Use the [Optimize application](/core-resources/bubbles-interface/settings-tab.md#optimize-application) feature to delete the field for good.

</details>

<details>

<summary>Why is there no password field on the user data type?</summary>

There isn't a visible password field because Bubble doesn't store passwords in a way you can access or reference like a regular field. Passwords are hashed and stored separately from the rest of the user's data, specifically for security. If passwords showed up as a normal field, they'd be readable and editable the same way as a name or email, which would be a serious security risk if that data were ever exposed.

No one has access to the password, not even you as the project's developer.

</details>

### Other ways to learn

<details>

<summary><mark style="color:blue;">Video lessons</mark></summary>

* [The data tab](https://www.youtube.com/watch?v=z0L8vFsCwkk)
* [Creating the data structure](https://www.youtube.com/watch?v=2NO1ET1bMLM)
* [Naming your data types](https://youtu.be/XueeVCReuI8)
* [How to add a data type as a custom field](https://youtu.be/4txlG9nwr1E)
* [How to create a field that holds a list](https://youtu.be/w2xJ_RhAfMk)

</details>

<details>

<summary><mark style="color:blue;">Articles</mark></summary>

* **Planning your database structure**\
  This article takes an introductory look at how to plan the database structure for your app.\
  \
  Article: [Planning your database structure](/help-guides/getting-started/building-your-first-app/database-structure.md)
* **Maintaining your database**\
  Keeping your database clean and up to date helps your app run efficiently and makes it easier for you to stay on top of the data. Check out the article series below for different ways of maintaining your database.\
  \
  Article series: [Maintaining your database](/help-guides/maintaining-an-application/database-maintenance.md)

</details>

[^1]: You can load data onto a page by setting the page's **Type of content** to the data type you want it to load, then using the **Go to page** action to specify the thing to load.

    Reference: [Go to page](/core-resources/bubble-workflows/bubble-actions/navigation-actions-in-web-apps.md#go-to-page)

[^2]: The **Make changes to a thing** action writes changes to the fields of a data type.

    For example, you could save the name Lisa in a *name* field on the current user, to store it permanently in the database.

    **Reference:** [Make changes to a thing](/core-resources/bubble-workflows/bubble-actions/database-actions.md#make-changes-to-thing)

[^3]: The **Set a thing's slug** action updates the slug field on a database thing.

    Bubble automatically applies the formatting needed to make the slug URL-friendly.

    Reference: [Set a thing's slug](/core-resources/bubble-workflows/bubble-actions/database-actions.md#set-a-things-slug)

[^4]: Removes unused or outdated content from your app to help improve performance. This may include old styles or deleted data types. Once optimized, some items, like deleted data types, can no longer be restored.

    Reference: Optimize app
