Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Standard and Enterprise editions

Firestore databases come in two editions, Standard and Enterprise. The library supports both, and some features need Enterprise. Every page of this book applies to both editions, unless its title, or the part of the book it sits in, names one edition, or a section “On the Enterprise edition” lists what differs.

The edition belongs to a database, not to the project: one project can hold databases of both editions, and the client picks one by its ID, see Client instance and lifecycle.

What each edition runs

The API column names the API a row is about: Core queries, pipelines, SQL, Admin for index management, TTL and bulk delete, or Any for a row that belongs to no one API. “Pipeline, SQL” marks a row where both behave the same. A number points to the notes under the table.

FeatureAPIStandardEnterprise
Reads and queriesCoreyesyes
Reads and queriesPipeline, SQLfails1yes
Writes and batch writesCoreyesyes
WritesPipeline, SQLnoyes
Query that no index coversCorefails2table scan3
Query that no index coversPipeline, SQLnotable scan4
Aggregations: count, sum, avgCoreyesyes, same results
TransactionsAnyyesyes5
Query plansCore.explain()rejected6
Query plansPipeline, SQLno.explain()6
Vector searchCoreneeds a vector index7no index needed8
Vector searchPipelinenotable scan9
Text and geo searchPipeline, SQLnoneeds a search index
ListenersCoreyesneeds real-time updates
CachingCoreyesneeds real-time updates
CachingPipeline, SQLonly if the cache answers in fullneeds real-time updates
Automatic single-field indexesAdminyesnone
Single-field overridesAdminyesnone10
Composite index of one fieldAdmina vector field onlyyes
Unique indexesAdminnoyes
Index density11AdminSparseAll onlyDense by default, or SparseAny12
__name__ appended to an indexAdminyesno
TTL policyAdminyesyes
Index statementsSQLyesyes
Bulk deleteAdminyesyes
Firestore emulatorAnythe default emulatorstarted with --edition=enterprise
BillingAnyper document read, written and deletedread units and write units13

Telling which edition a database is

gcloud firestore databases describe prints the settings of a database, among them its edition, its real-time updates mode and its concurrency mode:

gcloud firestore databases describe --database=my-database

These lines of its output name the three settings:

concurrencyMode: OPTIMISTIC
databaseEdition: ENTERPRISE
realtimeUpdatesMode: REALTIME_UPDATES_MODE_ENABLED

The Firestore page of the Google Cloud console lists the databases of a project with the edition of each.

With the admin feature, FirestoreDb::read_database_edition() returns the edition of the database the client is connected to. A database that reports no edition reads as Standard, the edition Firestore applies at creation. An edition this version of the crate does not know reads as Unknown, with the value Firestore reported. Firestore may add editions, so FirestoreDatabaseEdition is non-exhaustive. The emulator does not serve the Admin API, so the call fails there with UNIMPLEMENTED.

use firestore::*;
async fn example(db: FirestoreDb) -> FirestoreResult<()> {
match db.read_database_edition().await? {
    FirestoreDatabaseEdition::Standard => println!("Standard edition"),
    FirestoreDatabaseEdition::Enterprise => println!("Enterprise edition"),
    other => println!("an edition this version does not know: {other:?}"),
}
Ok(())
}

Two errors also tell the editions apart: a pipeline sent to a Standard edition database fails with FAILED_PRECONDITION, and a Core .explain() sent to an Enterprise edition database fails with INVALID_ARGUMENT, “Explain options are not supported in RunQuery API for Enterprise edition”.

Index management reads the edition itself, the same way, on every .plan() and .sync(), and follows the rules of that edition.

Settings fixed at creation

The edition and the real-time updates setting are immutable: to change either, create a new database with the wanted settings and move the data. Both are chosen when the database is created:

gcloud firestore databases create --database=my-database --edition=enterprise \
  --location=nam5 --enable-firestore-data-access --enable-realtime-updates

Google’s documentation does not agree on the default of real-time updates for an Enterprise edition database, so set --enable-realtime-updates explicitly when the database needs listeners or a cache.

Limits

  • a pipeline or SQL statement sent to a Standard edition database fails at once with FAILED_PRECONDITION, and the library does not retry it;
  • a search without a search index that covers it fails with FAILED_PRECONDITION, see Pipeline search;
  • joins and subqueries are in Preview, see Pipeline aggregations and joins;
  • Firestore rejects an atomic pipeline or SQL write that is too big, see Write limits;
  • Firestore has no setting that rejects a table scan, see Query plans and cost;
  • a Core .explain() is rejected on Enterprise. The same query written as a pipeline or SQL returns its plan through .explain(), see Explaining a pipeline.

Query and write semantics

A pipeline and a SQL statement keep Firestore’s pipeline semantics, which differ from a Core query in a few places: not_equal matches a document that lacks the field, sort keeps such documents, and the stages run in the order they are written. Query and write semantics lists every difference, with the SQL spelling of each.

Indexes

An Enterprise edition database builds no index on its own, takes indexes of one field, unique and dense indexes, and search indexes. A Standard edition database indexes every field automatically, and takes single-field overrides. See Composite and vector indexes, Search indexes and TTL and the Enterprise edition for the rules, and Waiting for changes to finish for the build times to expect on each edition.

Cost

Standard bills each document read, written and deleted; Enterprise bills read units (4 KiB) and write units (1 KiB, one more per indexed field) instead, and real-time updates as a separate charge. A read unit is 4 KiB of data, documents or index entries, that a read processes, so an Enterprise read costs by the data it scans. The rates are on Google’s pricing pages, for Standard and Enterprise. Query plans and cost shows how to read what a query costs.

Which API to use

Choosing Core queries, pipelines or SQL lists when each API fits, on each edition.


  1. A pipeline or SQL statement sent to a Standard edition database fails with FAILED_PRECONDITION, unless a cache session answers it. ↩

  2. FAILED_PRECONDITION, “The query requires an index”. ↩

  3. The query reads every document of the collection. Without order_by the order of its results is unspecified. ↩

  4. A pipeline or SQL statement that no index covers runs as a table scan. A search is the exception: it needs a search index and fails without one, see Known table scans. ↩

  5. Optimistic by default, so under contention more attempts abort and are retried. ↩

  6. An Enterprise edition database rejects a Core .explain() with INVALID_ARGUMENT, so explain the same query as a pipeline or SQL, see Explaining a pipeline. ↩ ↩2

  7. Without a vector index the query fails with FAILED_PRECONDITION. ↩

  8. A vector index can still be created on Enterprise, but whether a Core query uses it cannot be seen, since Core .explain() is rejected there. ↩

  9. The find_nearest stage reads every document with or without a vector index, and a filter before it does not narrow the read. Google lists this as a known issue of pipelines. Use a Core find_nearest where the index should be used, see Vector search. ↩

  10. An .exempt() is already satisfied. ↩

  11. The density of an index is which documents it holds an entry for. ↩

  12. A search index is SparseAny. ↩

  13. Real-time updates are billed separately. ↩