# What Data Types Can Be Stored in a FlutterFlow Database?

- Tool: FlutterFlow
- Difficulty: Intermediate
- Time required: 20-30 min
- Compatibility: FlutterFlow Free+ with Firebase Firestore or Supabase
- Last updated: March 2026

## TL;DR

FlutterFlow's Firestore database supports ten data types: String, Integer, Double, Boolean, Timestamp, GeoPoint, DocumentReference, Array, Map, and Null. Choose types carefully — storing prices as String instead of Double prevents range queries. Timestamps must be used for dates. DocumentReference creates relationships between documents. Arrays and Maps store structured nested data. Supabase (PostgreSQL) is available as an alternative for complex relational data with SQL types.

## Choosing the right data type is the foundation of a reliable FlutterFlow app

Every field in your FlutterFlow Firestore database has a type. The type determines what values the field can store, how it can be queried and sorted, and which FlutterFlow widgets can bind to it. Choosing the wrong type creates subtle bugs: storing a price as String means you cannot query for products under $50. Storing a date as String means you cannot sort by date or use date arithmetic. This guide covers every data type available in FlutterFlow's Firestore panel, when to use each, what widget it maps to, and the most common mistakes to avoid. It also compares Firestore types to Supabase PostgreSQL types for developers considering the relational database option.

## Before you start

- FlutterFlow project with Firebase Firestore enabled
- Basic understanding of Firestore collections and documents in FlutterFlow
- Access to FlutterFlow's Firestore panel for field type selection

## Step-by-step guide

### 1. String, Integer, and Double — the basic scalar types

String stores text: names, email addresses, descriptions, status values ('active', 'pending', 'cancelled'), and URL strings. Maximum field size: 1MB (a single field), but keep fields under 1KB for performance. Integer stores whole numbers without decimal points: counts (likeCount, viewCount, quantity), ages, item counts, and sequential numbering. Supports range queries (count > 100), arithmetic, and ordering. Double stores decimal numbers: prices (29.99), coordinates (latitude: 37.7749), percentages (0.85), and measurements. IMPORTANT: always use Double for prices, never String. In FlutterFlow's Firestore panel, click the field type dropdown and select String, Integer, or Double when creating the field. String fields bind to Text widgets, Integer and Double bind to Text widgets with Custom Function formatting.

**Expected result:** Scalar fields are configured with appropriate types so range queries, arithmetic, and sorting work correctly.

### 2. Boolean and Timestamp — flags and dates

Boolean stores true/false values: isActive, isVerified, isPremium, hasCompletedOnboarding, isFeatured. In FlutterFlow, Boolean fields bind to Switch and Checkbox widgets. Use Boolean fields in Backend Query conditions for filtering (isActive == true). Timestamp stores date and time values in UTC. ALWAYS use Timestamp for any date-related field — not String, not Integer (Unix epoch is acceptable but less readable). Timestamps support range queries (createdAt > yesterday's timestamp), date arithmetic in Cloud Functions, and proper ordering. In FlutterFlow, Timestamp fields bind to DateTimePicker widgets and display via Custom Functions that format them as human-readable strings. Set the value using Current Date Time in action flows or FieldValue.serverTimestamp() for write-time precision.

```
// Custom Function: formatTimestamp
// Converts a Firestore Timestamp to a readable string
// Parameters: timestamp (DateTime in FlutterFlow)
String formatTimestamp(DateTime timestamp) {
  final now = DateTime.now();
  final diff = now.difference(timestamp);

  if (diff.inMinutes < 1) return 'just now';
  if (diff.inMinutes < 60)
    return '${diff.inMinutes}m ago';
  if (diff.inHours < 24)
    return '${diff.inHours}h ago';
  if (diff.inDays < 7)
    return '${diff.inDays}d ago';

  // Fallback to date string
  return '${timestamp.day}/${timestamp.month}'
         '/${timestamp.year}';
}
```

**Expected result:** Date and flag fields use correct types enabling date-range queries, sorting, and proper widget binding.

### 3. GeoPoint and DocumentReference — location and relationships

GeoPoint stores a geographic coordinate as a latitude/longitude pair. Use it for user locations, store addresses, delivery points, and any map-related data. In FlutterFlow, GeoPoint fields provide latitude and longitude as separate Double values that you can use as inputs to FlutterFlowGoogleMap markers. Firestore does not support native geospatial queries (no 'find all points within 5km') — use the geoflutterfire2 package or the GeoHash pattern for proximity queries. DocumentReference stores a pointer (reference) to another Firestore document. This is how you create relationships between documents: an order document has a userId field of type DocumentReference pointing to the user document. In FlutterFlow, DocumentReference fields enable document lookup — you can fetch the referenced document in a Backend Query. Use DocumentReference for one-to-many relationships (order → user, comment → post).

**Expected result:** Location data uses GeoPoint type for map integration; related documents use DocumentReference for efficient lookups.

### 4. Array and Map — structured nested data

Array stores an ordered list of values, all of the same type: a list of tag strings, a list of UIDs for liked users, a list of product IDs in a wishlist. Firestore supports arrayContains and arrayContainsAny filter operators for arrays. Maximum array size: bounded by the 1MB document limit (avoid unbounded arrays, use subcollections for growing lists). In FlutterFlow, Array fields appear as List variables — iterate them with Generate Dynamic Children on a ListView. Map stores a nested object (key-value pairs) inside a document field: an address Map with street, city, state, zip keys; a metadata Map with version, source, processedAt keys. Map fields do not support direct querying in Firestore (you cannot WHERE address.city == 'NYC') — use top-level fields for frequently queried data. In FlutterFlow, access Map fields using field.key notation.

**Expected result:** Lists of values use Array type; nested structured data uses Map type with understanding of their query limitations.

### 5. Compare Firestore types to Supabase PostgreSQL types

If your app has complex relational needs, Supabase (PostgreSQL) is available as an alternative backend in FlutterFlow via Settings → Integrations → Supabase. PostgreSQL types map roughly as: TEXT (like String), INTEGER / BIGINT (like Integer), FLOAT8 / NUMERIC (like Double), BOOLEAN (like Boolean), TIMESTAMPTZ (like Timestamp with timezone), POINT (like GeoPoint but with native spatial queries via PostGIS), UUID (like String but for IDs), JSONB (like Map but queryable with ->> operator), TEXT[] or INTEGER[] (like Array but supports JOINs via ANY()). Key Supabase advantages over Firestore for type handling: SQL supports SUM, AVG, COUNT on numeric fields (Firestore cannot), NUMERIC type prevents floating-point rounding errors in financial calculations, TIMESTAMPTZ handles timezone-aware date math correctly, and FOREIGN KEY enforces DocumentReference-style relationships at the database level.

**Expected result:** You understand when Supabase's type system offers advantages for your specific data model over Firestore types.

## Complete code example

File: `firestore_type_reference.txt`

```text
FlutterFlow Firestore Data Type Reference

TYPE          FLUTTER TYPE    USE FOR              QUERY SUPPORT
-----------   ------------    -------------------  ---------------
String        String          names, emails,       ==, !=,
                              status, URLs         >, <, >=, <=,
                                                   array-contains

Integer       int             counts, ages,        ==, !=,
                              quantities           >, <, >=, <=

Double        double          prices, coords,      ==, !=,
                              percentages          >, <, >=, <=

Boolean       bool            flags, toggles       == true/false

Timestamp     DateTime        dates, times         ==, !=,
                              (always UTC)         >, <, >=, <=

GeoPoint      LatLng          coordinates,         == only
                              locations            (use GeoHash
                                                   for proximity)

DocRef        DocumentRef     relationships        == only
                              (pointer to doc)     (fetch doc)

Array         List<T>         tags, UIDs,          array-contains
                              product lists        arrayContainsAny

Map           Map<String,T>   address, metadata,   not queryable
                              settings             (use top-level
                                                   for queries)

Null          null            absent values        isNull / notNull

COMMON MISTAKES:
  Price as String   → cannot range query
  Date as String    → cannot sort/filter
  Count as String   → cannot do math
  Array unbounded   → hits 1MB document limit
  Map for queries   → cannot filter by map key
```

## Common mistakes

- **Storing prices as String ('19.99') instead of Double (19.99)** — String fields cannot be used in range queries or arithmetic. WHERE price < 50 fails on a String field because Firestore compares strings lexicographically ('9.99' > '50.00' in string comparison). You also cannot sort products by price or calculate totals in Cloud Functions without first converting the string to a number. Fix: Use Double for all numeric values that you will query, sort, or calculate. If you need to display prices with currency symbols, use a Custom Function to format the Double as a string for display only: formatPrice(product.price) returns '$19.99'.
- **Using an Array inside a document for data that will grow indefinitely** — Firestore documents have a 1MB size limit. An Array of message texts, order items, or activity events grows without bound. After enough data accumulates, the array update fails with a Document exceeds maximum size error, and all new writes to that document fail. Fix: Use subcollections for data that grows over time. Instead of user.orderHistory as an Array, create an orders/{userId}/items/{itemId} subcollection. Each item is an independent document that can be individually queried, paginated, and indexed.
- **Storing dates as formatted strings ('2024-03-15') instead of Timestamps** — String dates can be sorted alphabetically which happens to work for ISO 8601 format, but you lose: date arithmetic (add 30 days, calculate age), Firestore Timestamp range queries with proper UTC handling, and the ability to use Current Date Time directly in FlutterFlow without string formatting. Fix: Always use Timestamp type for dates and times. FlutterFlow maps Timestamp to DateTime natively. Use DateTimePicker for user input, Current Date Time for now(), and Custom Functions for any formatting needed for display.

## Best practices

- Document your Firestore schema with the collection name, field names, and types in a text file shared with your team — field names are case-sensitive and a typo breaks every query using that field
- Use String for enum-like values (status: 'active', 'pending', 'completed') and validate them in Firestore security rules with the in operator
- Prefer Integer over Double for counts and quantities to avoid floating-point arithmetic surprises in calculations
- Never store sensitive data like passwords, API keys, or payment card numbers in Firestore documents — use Firebase Auth for passwords and Cloud Functions for handling payment data
- Use DocumentReference fields for one-to-many relationships (post has an authorId DocumentReference pointing to the users collection) rather than duplicating user data in every post
- Add a createdAt Timestamp and updatedAt Timestamp to every document — these are essential for debugging, sorting, and audit trails
- For Supabase users: use NUMERIC(10,2) instead of FLOAT8 for financial amounts to avoid floating-point rounding errors in currency calculations

## Frequently asked questions

### Can I change a Firestore field's data type after the collection is created?

In FlutterFlow's Firestore panel, you cannot change the type of an existing field — you must delete and recreate it. However, Firestore itself is schemaless, so the actual stored data type is set per document when you write it. To migrate existing data to a new type (e.g., price from String to Double), write a Firebase Cloud Function that reads each document, converts the field value, and writes it back. Test on a small batch first before running on all documents.

### What is the difference between Integer and Double in FlutterFlow?

Integer stores whole numbers with no decimal component: 1, 42, 1000. It is perfect for counts, quantities, and sequential IDs. Double stores decimal numbers: 19.99, 3.14, 0.85. Use Double for prices, percentages, GPS coordinates, and measurements. Using Double for a count field works functionally but wastes bytes and can cause unexpected decimal values in arithmetic. Using Integer for a price field causes all prices to round to whole numbers.

### How do I store a list of user IDs (UIDs) in a Firestore document?

Use an Array of String type. In FlutterFlow's Firestore panel, add a field with type Array and set the array element type to String. Store each UID as a string element in the array (e.g., likedBy: ['uid123', 'uid456', 'uid789']). Query documents where a specific user has liked: use the arrayContains filter operator in your Backend Query with the current user's UID as the value. Use FieldValue.arrayUnion and FieldValue.arrayRemove in Update Document actions to add and remove UIDs without replacing the entire array.

### When should I use a Map field vs creating separate top-level fields?

Use a Map when the sub-fields are always read together and never individually queried. Address is a perfect Map candidate — you always show the full address together and never need to query WHERE address.city == 'London'. Use separate top-level fields when you need to query, sort, or filter by individual sub-values. A product's price and category should be separate top-level fields (not inside a details Map) because you filter by price and category constantly.

### What data type should I use for storing files and images?

Never store binary file data in Firestore — the document size limit is 1MB and images are typically larger. Store files in Firebase Storage. In Firestore, store the download URL as a String field pointing to the Firebase Storage file. For multiple images, use an Array of Strings. For images with metadata, use an Array of Maps: [{url: 'https://...', caption: 'Front view', order: 1}].

### Does FlutterFlow support Supabase data types for apps using PostgreSQL instead of Firestore?

Yes. When you connect Supabase via Settings → Integrations → Supabase, FlutterFlow reads your PostgreSQL schema and maps SQL types to Flutter types: TEXT → String, INTEGER → int, FLOAT8/NUMERIC → double, BOOLEAN → bool, TIMESTAMPTZ → DateTime, UUID → String, JSONB → dynamic/Map. You design your Supabase schema in the Supabase Dashboard SQL editor or Table Editor, then click Get Schema in FlutterFlow to import the types automatically.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/what-are-the-different-types-of-data-that-can-be-stored-in-a-flutterflow-database
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/what-are-the-different-types-of-data-that-can-be-stored-in-a-flutterflow-database
