Query Firestore data in FlutterFlow using the Backend Query panel — select a collection, add Where filters with operators (equals, less than, arrayContains, in), add Order By fields, and set a Limit for pagination. Use real-time mode (Single Time Query: OFF) for live data like chats, or one-time mode for static content. Compound queries with multiple Where conditions are supported but all inequality operators must be on the same field. For OR logic or JOIN-like queries, use Supabase instead of Firestore.
Read exactly the data you need from Firestore using FlutterFlow's Backend Query configuration
Firestore queries in FlutterFlow are configured visually in the Backend Query panel — no code required for most use cases. You select which collection to read, add filter conditions using Where clauses, specify sort order, and limit the result count. Understanding the constraints of Firestore's query model is essential: it is a document database, not a relational one. There are no JOINs. OR conditions across multiple fields are not supported natively. Inequality operators (less than, greater than) can only be applied to one field per query. These constraints shape how you design your Firestore schema and write your queries. For queries that require SQL-like flexibility, Supabase (FlutterFlow's built-in alternative) supports full SQL including OR, LIKE, and multi-table JOINs.
Prerequisites
- A FlutterFlow project with Firebase/Firestore configured (Settings → Project Setup → Firebase)
- At least one Firestore collection with documents to query
- Basic understanding of Firestore's document/collection model
- Understanding of FlutterFlow's widget tree — Backend Query results are available to all child widgets
Step-by-step guide
Set up a basic Backend Query on a page or widget
Set up a basic Backend Query on a page or widget
In FlutterFlow, click the page or widget where you want to display data. In the Properties Panel, click the Backend Query tab. Click Add Query. Select Query Collection from the Query Type dropdown. Select your collection from the Collection dropdown. The query runs immediately and makes all document fields available to child widgets via Set from Variable. For a simple 'load all items' query, you do not need any filters — just set a Limit (default is unlimited, but always set a practical limit like 50 to avoid loading thousands of documents). With the query configured, click any Text widget in the page → Set from Variable → Backend Query Result → select the field you want to display.
Expected result: The page loads documents from your collection and child widgets display the data. With no filters, all documents (up to the limit) appear.
Add Where filter conditions to narrow results
Add Where filter conditions to narrow results
In the Backend Query panel, click Add Filter under Filters. Each filter has three parts: the Field (select from your collection's fields), the Operator, and the Value. Available operators: == (equal to), != (not equal), > (greater than), >= (greater than or equal), < (less than), <= (less than or equal), array-contains (document's array field contains a specific value), array-contains-any (array contains any value from a list), in (field value matches any of a list, max 10 values), not-in (field value matches none of a list, max 10 values). For the Value, you can use a literal value, a Page State variable, App State variable, or the current user's UID. Example: filter orders where userId == currentUser.uid, status == 'pending'.
Expected result: The query only returns documents matching all filter conditions. Adding multiple filters creates AND logic — all conditions must be true.
Add Order By and implement pagination with Limit
Add Order By and implement pagination with Limit
In the Backend Query panel, click Add Sort under Order By. Select the field to sort on and choose Ascending or Descending. Commonly: sort orders by createdAt Descending (newest first), sort products by price Ascending (cheapest first), sort users by displayName Ascending (alphabetical). For Limit, enter a number like 20 or 50. Without a limit, Firestore reads all matching documents — expensive on large collections. For pagination (loading more items when user scrolls down), FlutterFlow supports cursor-based pagination: enable Paginate in the Backend Query settings, set the page size, and use the Load More action on your ListView to fetch the next page using the last document as the cursor. This uses Firestore's startAfterDocument internally.
Expected result: Results appear in the expected order. Pagination loads additional documents only when needed, keeping initial load fast and Firestore read costs low.
Choose between real-time and one-time queries
Choose between real-time and one-time queries
In the Backend Query panel, there is a Single Time Query toggle. When OFF (default for some configurations), the query is real-time — FlutterFlow establishes a persistent WebSocket connection to Firestore and updates the UI automatically whenever a matching document changes. When ON, the query runs once when the page loads and does not listen for changes. Use real-time (OFF) for: chat messages, live order status, collaborative editing, notifications count. Use one-time (ON) for: product catalogs, user profiles, settings, FAQ content, any data that changes rarely or only when the user explicitly refreshes. Each real-time query holds an open connection — having 10 real-time queries on one page drains battery and uses Firestore's listener quota.
Expected result: Data-sensitive pages (chat, live status) update automatically with real-time queries. Static content pages (product listings, help articles) load once and do not maintain open connections.
Handle Firestore query limitations with multi-query patterns or Supabase
Handle Firestore query limitations with multi-query patterns or Supabase
Firestore's query model has constraints that require workarounds: (1) OR conditions: Firestore does not support OR across different fields. Workaround: run two separate queries and merge results in App State using a Custom Action. (2) Inequality on multiple fields: you can only use inequality operators (>, <, >=, <=) on ONE field per query. Workaround: filter one condition in the query, filter the second condition client-side using a Custom Function on the result array. (3) Full-text search: Firestore does not support LIKE or text search. Workaround: use Algolia or Typesense with a Cloud Function sync. (4) Complex relational queries: if your use case requires JOIN-like operations across multiple collections, consider using Supabase (Settings → Integrations → Supabase) which supports full SQL with WHERE, OR, LIKE, and JOIN.
Expected result: You understand which query patterns are native to Firestore, which require workarounds, and which require switching to Supabase for full SQL support.
Complete working example
1Common Query Configurations in FlutterFlow Backend Query Panel:231. Load user's orders, newest first, limit 204 Collection: orders5 Filters:6 userId == [Authenticated User > uid]7 Order By: createdAt Descending8 Limit: 209 Single Time Query: ON10112. Show in-progress orders (real-time dashboard)12 Collection: orders13 Filters:14 status == 'processing'15 Order By: createdAt Ascending16 Single Time Query: OFF (real-time listener)17183. Products under $50 sorted by price19 Collection: products20 Filters:21 price <= 5022 isActive == true23 Order By: price Ascending24 Limit: 5025 NOTE: Two filters, but only one inequality (price) — valid26274. Posts tagged with 'flutter'28 Collection: posts29 Filters:30 tags array-contains 'flutter'31 Order By: createdAt Descending32 Limit: 2033345. Documents by one of several IDs35 Collection: products36 Filters:37 productId in ['id1', 'id2', 'id3'] (max 10 values)3839Not Supported Natively (require workarounds):40- price > 50 AND rating > 4.0 (two inequalities, different fields)41 FIX: filter price > 50 in query, filter rating > 4.0 client-side4243- status == 'active' OR status == 'pending' (OR condition)44 FIX: use 'in' operator: status in ['active', 'pending']4546- title LIKE '%flutter%' (full-text search)47 FIX: use Algolia or Typesense integration4849Supabase SQL equivalent (for relational needs):50 SELECT * FROM orders51 INNER JOIN users ON orders.user_id = users.id52 WHERE orders.status IN ('active', 'pending')53 AND orders.total > 5054 ORDER BY orders.created_at DESC55 LIMIT 20Common mistakes when querying Data from Your FlutterFlow Firestore Database
Why it's a problem: Using inequality operators on two different fields in the same query
How to avoid: Apply the inequality filter to the most selective field in the query (the one that eliminates the most documents). Then filter the second field client-side using a Custom Function that iterates over the query results and removes items that do not meet the second condition.
Why it's a problem: Leaving all Backend Queries as real-time (Single Time Query OFF) on every page
How to avoid: Set Single Time Query ON for any data that does not need to update live: product details, user profiles, settings, help content, historical records. Only use real-time for data that genuinely changes while the user is watching: chat messages, live order tracking, collaborative documents.
Why it's a problem: Not setting a Limit on queries against large collections
How to avoid: Always set a Limit on your Backend Query. For list views, 20-50 items per page is appropriate. Implement Load More pagination for users who need additional results rather than loading everything upfront.
Best practices
- Design your Firestore schema around the queries you need — denormalize data to avoid multi-collection lookups rather than trying to normalize like a relational database
- Use composite indexes for queries with multiple Where conditions or a combination of Where and Order By — Firestore error messages include a direct link to create the required index
- Test queries in Firebase Console → Firestore → Filter data before implementing them in FlutterFlow to confirm the query logic returns expected results
- Use the in operator instead of running multiple equality queries for up to 10 values: status in ['active', 'pending'] is one query, not two
- Store denormalized fields for common queries — if you frequently filter users by subscription tier, store tier as a top-level field on the user document, not nested in a subscription map
- Use collection group queries for querying the same subcollection name across all parent documents — for example, query all messages subcollections across all conversation documents at once
- Monitor your Firestore usage in Firebase Console → Firestore → Usage to identify which queries consume the most reads and optimize those first
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building a FlutterFlow app with Firestore. Explain how to configure queries in FlutterFlow's Backend Query panel for these scenarios: (1) load only the current user's orders sorted by date, (2) filter products under $50 with a minimum rating of 4 (noting the inequality limitation), (3) find posts containing a specific tag using array-contains, (4) implement Load More pagination using a limit and cursor. For each, describe the exact Backend Query settings and any client-side workarounds needed.
Set up a product listing page in my FlutterFlow app that queries the products Firestore collection filtered by category equals my selected category Page State variable, sorted by price ascending, with a limit of 20. Add a Load More button at the bottom that fetches the next 20 products using pagination. Show a loading indicator while the query is in-flight.
Frequently asked questions
How do I query data from Firestore in FlutterFlow?
Select a page or widget, click the Backend Query tab in Properties Panel, choose Query Collection, select your collection, and add filters using the Add Filter button. Each filter specifies a field, an operator (==, >, arrayContains, etc.), and a value. Add an Order By field and a Limit. Click Done. Child widgets can then access the query results via Set from Variable → Backend Query Result.
How do I filter Firestore results by the current logged-in user?
In the Backend Query filter, set the field to userId (or whichever field stores the user reference), operator to ==, and value to Authenticated User → uid. This filters the collection to only return documents belonging to the currently logged-in user. Make sure your Firestore security rules also enforce this restriction server-side.
Why is my FlutterFlow query returning empty results?
Common causes: the filter value is empty or null at query time (check that Page State or App State is initialized before the query runs), the field name in the filter does not exactly match the Firestore field name (case-sensitive), a required composite index is missing (check the Firebase Console Firestore indexes tab), or security rules are blocking the read (test in Rules Playground). Check each systematically.
Can I query across multiple Firestore collections at once?
Firestore does not support cross-collection queries (no JOIN equivalent). For subcollections with the same name under different parent documents, use a collection group query — select the subcollection name and FlutterFlow will query it across all parent documents. For combining data from two different collections, run two separate Backend Queries and merge the results using a Custom Action or Custom Function.
How do I search Firestore documents by text content (like a search bar)?
Firestore does not support full-text search. For simple prefix-matching (finding names starting with what the user typed), you can use >= and <= operators with a range query on a string field. For real search (containing, fuzzy matching), you need an external search index. Algolia and Typesense are the most popular choices — sync data to them from Firestore via Cloud Function triggers and query them from FlutterFlow via the API Manager.
What is the difference between Firestore queries and Supabase queries in FlutterFlow?
Firestore uses a document/collection model with a limited query API: no JOINs, no OR across fields, no LIKE, inequality only on one field per query. Supabase uses PostgreSQL with full SQL: JOINs between tables, WHERE with OR and AND, LIKE for text search, aggregate functions, and complex subqueries. If your data has strong relationships or requires complex filtering, Supabase is often a better fit than Firestore.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation