The gcp:firestore/database:Database resource, part of the Pulumi GCP provider, provisions a Cloud Firestore database: its mode (Native or Datastore), location, and operational features like encryption and recovery. This guide focuses on four capabilities: Native and Datastore mode selection, point-in-time recovery and deletion protection, customer-managed encryption with Cloud KMS, and Enterprise edition provisioning.
Firestore databases belong to a GCP project and require the Firestore API to be enabled. CMEK configurations depend on pre-existing KMS keys and IAM bindings. The examples are intentionally small. Combine them with your own project configuration and security policies.
Create the default database in Native mode
Most projects start with a single default database in Firestore Native mode, which provides real-time synchronization and mobile SDKs for document storage.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const database = new gcp.firestore.Database("database", {
project: "my-project-name",
name: "(default)",
locationId: "nam5",
type: "FIRESTORE_NATIVE",
});
import pulumi
import pulumi_gcp as gcp
database = gcp.firestore.Database("database",
project="my-project-name",
name="(default)",
location_id="nam5",
type="FIRESTORE_NATIVE")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firestore"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := firestore.NewDatabase(ctx, "database", &firestore.DatabaseArgs{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("(default)"),
LocationId: pulumi.String("nam5"),
Type: pulumi.String("FIRESTORE_NATIVE"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var database = new Gcp.Firestore.Database("database", new()
{
Project = "my-project-name",
Name = "(default)",
LocationId = "nam5",
Type = "FIRESTORE_NATIVE",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firestore.Database;
import com.pulumi.gcp.firestore.DatabaseArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var database = new Database("database", DatabaseArgs.builder()
.project("my-project-name")
.name("(default)")
.locationId("nam5")
.type("FIRESTORE_NATIVE")
.build());
}
}
resources:
database:
type: gcp:firestore:Database
properties:
project: my-project-name
name: (default)
locationId: nam5
type: FIRESTORE_NATIVE
The name property uses the special value “(default)” to create the project’s primary database. The type property set to “FIRESTORE_NATIVE” enables document and collection storage with real-time listeners. The locationId determines where data is stored; once set, it cannot be changed.
Configure concurrency, recovery, and deletion protection
Production databases often enable point-in-time recovery for data restoration, optimistic concurrency for write performance, and deletion protection to prevent accidental removal.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const database = new gcp.firestore.Database("database", {
project: "my-project-name",
name: "database-id",
locationId: "nam5",
type: "FIRESTORE_NATIVE",
concurrencyMode: "OPTIMISTIC",
appEngineIntegrationMode: "DISABLED",
pointInTimeRecoveryEnablement: "POINT_IN_TIME_RECOVERY_ENABLED",
deleteProtectionState: "DELETE_PROTECTION_ENABLED",
deletionPolicy: "DELETE",
});
import pulumi
import pulumi_gcp as gcp
database = gcp.firestore.Database("database",
project="my-project-name",
name="database-id",
location_id="nam5",
type="FIRESTORE_NATIVE",
concurrency_mode="OPTIMISTIC",
app_engine_integration_mode="DISABLED",
point_in_time_recovery_enablement="POINT_IN_TIME_RECOVERY_ENABLED",
delete_protection_state="DELETE_PROTECTION_ENABLED",
deletion_policy="DELETE")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firestore"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := firestore.NewDatabase(ctx, "database", &firestore.DatabaseArgs{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("database-id"),
LocationId: pulumi.String("nam5"),
Type: pulumi.String("FIRESTORE_NATIVE"),
ConcurrencyMode: pulumi.String("OPTIMISTIC"),
AppEngineIntegrationMode: pulumi.String("DISABLED"),
PointInTimeRecoveryEnablement: pulumi.String("POINT_IN_TIME_RECOVERY_ENABLED"),
DeleteProtectionState: pulumi.String("DELETE_PROTECTION_ENABLED"),
DeletionPolicy: pulumi.String("DELETE"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var database = new Gcp.Firestore.Database("database", new()
{
Project = "my-project-name",
Name = "database-id",
LocationId = "nam5",
Type = "FIRESTORE_NATIVE",
ConcurrencyMode = "OPTIMISTIC",
AppEngineIntegrationMode = "DISABLED",
PointInTimeRecoveryEnablement = "POINT_IN_TIME_RECOVERY_ENABLED",
DeleteProtectionState = "DELETE_PROTECTION_ENABLED",
DeletionPolicy = "DELETE",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firestore.Database;
import com.pulumi.gcp.firestore.DatabaseArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var database = new Database("database", DatabaseArgs.builder()
.project("my-project-name")
.name("database-id")
.locationId("nam5")
.type("FIRESTORE_NATIVE")
.concurrencyMode("OPTIMISTIC")
.appEngineIntegrationMode("DISABLED")
.pointInTimeRecoveryEnablement("POINT_IN_TIME_RECOVERY_ENABLED")
.deleteProtectionState("DELETE_PROTECTION_ENABLED")
.deletionPolicy("DELETE")
.build());
}
}
resources:
database:
type: gcp:firestore:Database
properties:
project: my-project-name
name: database-id
locationId: nam5
type: FIRESTORE_NATIVE
concurrencyMode: OPTIMISTIC
appEngineIntegrationMode: DISABLED
pointInTimeRecoveryEnablement: POINT_IN_TIME_RECOVERY_ENABLED
deleteProtectionState: DELETE_PROTECTION_ENABLED
deletionPolicy: DELETE
When pointInTimeRecoveryEnablement is set to “POINT_IN_TIME_RECOVERY_ENABLED”, Firestore retains data versions for 7 days, allowing reads against any timestamp within that window. The concurrencyMode property controls transaction behavior: “OPTIMISTIC” allows concurrent writes with conflict detection. The deleteProtectionState property prevents accidental deletion when set to “DELETE_PROTECTION_ENABLED”.
Encrypt data with customer-managed keys
Organizations with compliance requirements often control encryption keys through Cloud KMS rather than relying on Google-managed encryption.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = gcp.organizations.getProject({});
const keyRing = new gcp.kms.KeyRing("key_ring", {
name: "kms-key-ring",
location: "us",
});
const cryptoKey = new gcp.kms.CryptoKey("crypto_key", {
name: "kms-key",
keyRing: keyRing.id,
purpose: "ENCRYPT_DECRYPT",
});
const firestoreCmekKeyuser = new gcp.kms.CryptoKeyIAMBinding("firestore_cmek_keyuser", {
cryptoKeyId: cryptoKey.id,
role: "roles/cloudkms.cryptoKeyEncrypterDecrypter",
members: [project.then(project => `serviceAccount:service-${project.number}@gcp-sa-firestore.iam.gserviceaccount.com`)],
});
const database = new gcp.firestore.Database("database", {
project: "my-project-name",
name: "cmek-database-id",
locationId: "nam5",
type: "FIRESTORE_NATIVE",
concurrencyMode: "OPTIMISTIC",
appEngineIntegrationMode: "DISABLED",
pointInTimeRecoveryEnablement: "POINT_IN_TIME_RECOVERY_ENABLED",
deleteProtectionState: "DELETE_PROTECTION_ENABLED",
deletionPolicy: "DELETE",
cmekConfig: {
kmsKeyName: cryptoKey.id,
},
}, {
dependsOn: [firestoreCmekKeyuser],
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.get_project()
key_ring = gcp.kms.KeyRing("key_ring",
name="kms-key-ring",
location="us")
crypto_key = gcp.kms.CryptoKey("crypto_key",
name="kms-key",
key_ring=key_ring.id,
purpose="ENCRYPT_DECRYPT")
firestore_cmek_keyuser = gcp.kms.CryptoKeyIAMBinding("firestore_cmek_keyuser",
crypto_key_id=crypto_key.id,
role="roles/cloudkms.cryptoKeyEncrypterDecrypter",
members=[f"serviceAccount:service-{project.number}@gcp-sa-firestore.iam.gserviceaccount.com"])
database = gcp.firestore.Database("database",
project="my-project-name",
name="cmek-database-id",
location_id="nam5",
type="FIRESTORE_NATIVE",
concurrency_mode="OPTIMISTIC",
app_engine_integration_mode="DISABLED",
point_in_time_recovery_enablement="POINT_IN_TIME_RECOVERY_ENABLED",
delete_protection_state="DELETE_PROTECTION_ENABLED",
deletion_policy="DELETE",
cmek_config={
"kms_key_name": crypto_key.id,
},
opts = pulumi.ResourceOptions(depends_on=[firestore_cmek_keyuser]))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firestore"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/kms"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
project, err := organizations.LookupProject(ctx, &organizations.LookupProjectArgs{}, nil)
if err != nil {
return err
}
keyRing, err := kms.NewKeyRing(ctx, "key_ring", &kms.KeyRingArgs{
Name: pulumi.String("kms-key-ring"),
Location: pulumi.String("us"),
})
if err != nil {
return err
}
cryptoKey, err := kms.NewCryptoKey(ctx, "crypto_key", &kms.CryptoKeyArgs{
Name: pulumi.String("kms-key"),
KeyRing: keyRing.ID(),
Purpose: pulumi.String("ENCRYPT_DECRYPT"),
})
if err != nil {
return err
}
firestoreCmekKeyuser, err := kms.NewCryptoKeyIAMBinding(ctx, "firestore_cmek_keyuser", &kms.CryptoKeyIAMBindingArgs{
CryptoKeyId: cryptoKey.ID(),
Role: pulumi.String("roles/cloudkms.cryptoKeyEncrypterDecrypter"),
Members: pulumi.StringArray{
pulumi.Sprintf("serviceAccount:service-%v@gcp-sa-firestore.iam.gserviceaccount.com", project.Number),
},
})
if err != nil {
return err
}
_, err = firestore.NewDatabase(ctx, "database", &firestore.DatabaseArgs{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("cmek-database-id"),
LocationId: pulumi.String("nam5"),
Type: pulumi.String("FIRESTORE_NATIVE"),
ConcurrencyMode: pulumi.String("OPTIMISTIC"),
AppEngineIntegrationMode: pulumi.String("DISABLED"),
PointInTimeRecoveryEnablement: pulumi.String("POINT_IN_TIME_RECOVERY_ENABLED"),
DeleteProtectionState: pulumi.String("DELETE_PROTECTION_ENABLED"),
DeletionPolicy: pulumi.String("DELETE"),
CmekConfig: &firestore.DatabaseCmekConfigArgs{
KmsKeyName: cryptoKey.ID(),
},
}, pulumi.DependsOn([]pulumi.Resource{
firestoreCmekKeyuser,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var project = Gcp.Organizations.GetProject.Invoke();
var keyRing = new Gcp.Kms.KeyRing("key_ring", new()
{
Name = "kms-key-ring",
Location = "us",
});
var cryptoKey = new Gcp.Kms.CryptoKey("crypto_key", new()
{
Name = "kms-key",
KeyRing = keyRing.Id,
Purpose = "ENCRYPT_DECRYPT",
});
var firestoreCmekKeyuser = new Gcp.Kms.CryptoKeyIAMBinding("firestore_cmek_keyuser", new()
{
CryptoKeyId = cryptoKey.Id,
Role = "roles/cloudkms.cryptoKeyEncrypterDecrypter",
Members = new[]
{
$"serviceAccount:service-{project.Apply(getProjectResult => getProjectResult.Number)}@gcp-sa-firestore.iam.gserviceaccount.com",
},
});
var database = new Gcp.Firestore.Database("database", new()
{
Project = "my-project-name",
Name = "cmek-database-id",
LocationId = "nam5",
Type = "FIRESTORE_NATIVE",
ConcurrencyMode = "OPTIMISTIC",
AppEngineIntegrationMode = "DISABLED",
PointInTimeRecoveryEnablement = "POINT_IN_TIME_RECOVERY_ENABLED",
DeleteProtectionState = "DELETE_PROTECTION_ENABLED",
DeletionPolicy = "DELETE",
CmekConfig = new Gcp.Firestore.Inputs.DatabaseCmekConfigArgs
{
KmsKeyName = cryptoKey.Id,
},
}, new CustomResourceOptions
{
DependsOn =
{
firestoreCmekKeyuser,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetProjectArgs;
import com.pulumi.gcp.kms.KeyRing;
import com.pulumi.gcp.kms.KeyRingArgs;
import com.pulumi.gcp.kms.CryptoKey;
import com.pulumi.gcp.kms.CryptoKeyArgs;
import com.pulumi.gcp.kms.CryptoKeyIAMBinding;
import com.pulumi.gcp.kms.CryptoKeyIAMBindingArgs;
import com.pulumi.gcp.firestore.Database;
import com.pulumi.gcp.firestore.DatabaseArgs;
import com.pulumi.gcp.firestore.inputs.DatabaseCmekConfigArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var project = OrganizationsFunctions.getProject(GetProjectArgs.builder()
.build());
var keyRing = new KeyRing("keyRing", KeyRingArgs.builder()
.name("kms-key-ring")
.location("us")
.build());
var cryptoKey = new CryptoKey("cryptoKey", CryptoKeyArgs.builder()
.name("kms-key")
.keyRing(keyRing.id())
.purpose("ENCRYPT_DECRYPT")
.build());
var firestoreCmekKeyuser = new CryptoKeyIAMBinding("firestoreCmekKeyuser", CryptoKeyIAMBindingArgs.builder()
.cryptoKeyId(cryptoKey.id())
.role("roles/cloudkms.cryptoKeyEncrypterDecrypter")
.members(String.format("serviceAccount:service-%s@gcp-sa-firestore.iam.gserviceaccount.com", project.number()))
.build());
var database = new Database("database", DatabaseArgs.builder()
.project("my-project-name")
.name("cmek-database-id")
.locationId("nam5")
.type("FIRESTORE_NATIVE")
.concurrencyMode("OPTIMISTIC")
.appEngineIntegrationMode("DISABLED")
.pointInTimeRecoveryEnablement("POINT_IN_TIME_RECOVERY_ENABLED")
.deleteProtectionState("DELETE_PROTECTION_ENABLED")
.deletionPolicy("DELETE")
.cmekConfig(DatabaseCmekConfigArgs.builder()
.kmsKeyName(cryptoKey.id())
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(firestoreCmekKeyuser)
.build());
}
}
resources:
database:
type: gcp:firestore:Database
properties:
project: my-project-name
name: cmek-database-id
locationId: nam5
type: FIRESTORE_NATIVE
concurrencyMode: OPTIMISTIC
appEngineIntegrationMode: DISABLED
pointInTimeRecoveryEnablement: POINT_IN_TIME_RECOVERY_ENABLED
deleteProtectionState: DELETE_PROTECTION_ENABLED
deletionPolicy: DELETE
cmekConfig:
kmsKeyName: ${cryptoKey.id}
options:
dependsOn:
- ${firestoreCmekKeyuser}
cryptoKey:
type: gcp:kms:CryptoKey
name: crypto_key
properties:
name: kms-key
keyRing: ${keyRing.id}
purpose: ENCRYPT_DECRYPT
keyRing:
type: gcp:kms:KeyRing
name: key_ring
properties:
name: kms-key-ring
location: us
firestoreCmekKeyuser:
type: gcp:kms:CryptoKeyIAMBinding
name: firestore_cmek_keyuser
properties:
cryptoKeyId: ${cryptoKey.id}
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
members:
- serviceAccount:service-${project.number}@gcp-sa-firestore.iam.gserviceaccount.com
variables:
project:
fn::invoke:
function: gcp:organizations:getProject
arguments: {}
The cmekConfig block references a KMS crypto key for encryption. Before creating the database, you must grant the Firestore service account the cryptoKeyEncrypterDecrypter role on the key. The dependsOn property ensures the IAM binding completes before database creation. The KMS key location must be compatible with the database location.
Create the default database in Datastore mode
Applications migrating from Cloud Datastore or requiring Datastore’s entity-based model can provision databases in Datastore mode for backward compatibility.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const datastoreModeDatabase = new gcp.firestore.Database("datastore_mode_database", {
project: "my-project-name",
name: "(default)",
locationId: "nam5",
type: "DATASTORE_MODE",
});
import pulumi
import pulumi_gcp as gcp
datastore_mode_database = gcp.firestore.Database("datastore_mode_database",
project="my-project-name",
name="(default)",
location_id="nam5",
type="DATASTORE_MODE")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firestore"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := firestore.NewDatabase(ctx, "datastore_mode_database", &firestore.DatabaseArgs{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("(default)"),
LocationId: pulumi.String("nam5"),
Type: pulumi.String("DATASTORE_MODE"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var datastoreModeDatabase = new Gcp.Firestore.Database("datastore_mode_database", new()
{
Project = "my-project-name",
Name = "(default)",
LocationId = "nam5",
Type = "DATASTORE_MODE",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firestore.Database;
import com.pulumi.gcp.firestore.DatabaseArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var datastoreModeDatabase = new Database("datastoreModeDatabase", DatabaseArgs.builder()
.project("my-project-name")
.name("(default)")
.locationId("nam5")
.type("DATASTORE_MODE")
.build());
}
}
resources:
datastoreModeDatabase:
type: gcp:firestore:Database
name: datastore_mode_database
properties:
project: my-project-name
name: (default)
locationId: nam5
type: DATASTORE_MODE
Setting type to “DATASTORE_MODE” creates a database that uses the Datastore API and entity model instead of Firestore’s document model. This mode is useful for applications already built on Datastore or requiring its specific features like entity groups.
Provision an Enterprise edition database
High-throughput applications requiring enhanced performance and SLA guarantees can use the Enterprise edition, which provides higher limits and dedicated capacity.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const enterprise_db = new gcp.firestore.Database("enterprise-db", {
project: "my-project-name",
name: "database-id",
locationId: "nam5",
type: "FIRESTORE_NATIVE",
databaseEdition: "ENTERPRISE",
deletionPolicy: "DELETE",
});
import pulumi
import pulumi_gcp as gcp
enterprise_db = gcp.firestore.Database("enterprise-db",
project="my-project-name",
name="database-id",
location_id="nam5",
type="FIRESTORE_NATIVE",
database_edition="ENTERPRISE",
deletion_policy="DELETE")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/firestore"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := firestore.NewDatabase(ctx, "enterprise-db", &firestore.DatabaseArgs{
Project: pulumi.String("my-project-name"),
Name: pulumi.String("database-id"),
LocationId: pulumi.String("nam5"),
Type: pulumi.String("FIRESTORE_NATIVE"),
DatabaseEdition: pulumi.String("ENTERPRISE"),
DeletionPolicy: pulumi.String("DELETE"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var enterprise_db = new Gcp.Firestore.Database("enterprise-db", new()
{
Project = "my-project-name",
Name = "database-id",
LocationId = "nam5",
Type = "FIRESTORE_NATIVE",
DatabaseEdition = "ENTERPRISE",
DeletionPolicy = "DELETE",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.firestore.Database;
import com.pulumi.gcp.firestore.DatabaseArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var enterprise_db = new Database("enterprise-db", DatabaseArgs.builder()
.project("my-project-name")
.name("database-id")
.locationId("nam5")
.type("FIRESTORE_NATIVE")
.databaseEdition("ENTERPRISE")
.deletionPolicy("DELETE")
.build());
}
}
resources:
enterprise-db:
type: gcp:firestore:Database
properties:
project: my-project-name
name: database-id
locationId: nam5
type: FIRESTORE_NATIVE
databaseEdition: ENTERPRISE
deletionPolicy: DELETE
The databaseEdition property set to “ENTERPRISE” provisions a database with higher throughput limits and dedicated capacity. This edition is immutable once set and requires explicit configuration at creation time.
Beyond these examples
These snippets focus on specific database-level features: Native and Datastore mode databases, point-in-time recovery and deletion protection, customer-managed encryption keys, and Enterprise edition provisioning. They’re intentionally minimal rather than full data platform deployments.
The examples may reference pre-existing infrastructure such as GCP projects with Firestore API enabled, and KMS key rings, crypto keys, and IAM bindings for Firestore service accounts (for CMEK examples). They focus on configuring the database rather than provisioning the surrounding infrastructure.
To keep things focused, common database patterns are omitted, including:
- Resource manager tags (tags property)
- App Engine integration mode configuration
- Concurrency mode selection (OPTIMISTIC vs PESSIMISTIC)
- Database naming constraints and validation
These omissions are intentional: the goal is to illustrate how each database feature is wired, not provide drop-in data platform modules. See the Firestore Database resource reference for all available configuration options.
Let's deploy GCP Cloud Firestore Databases
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Selection & Setup
gcp.appengine.Application if you need Firestore with App Engine. Use gcp.firestore.Database for standalone Firestore databases. If migrating from gcp.appengine.Application to gcp.firestore.Database, follow the migration instructions in the GCP documentation.type property. FIRESTORE_NATIVE provides the full Firestore feature set, while DATASTORE_MODE provides Datastore compatibility. See the GCP documentation for guidance on choosing between them.Database Configuration
(default) creates the default database for your project, as shown in the default database examples.[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}). The special name (default) is also valid.databaseEdition property accepts STANDARD or ENTERPRISE values. This property is immutable after creation, so choose carefully during initial setup.Immutability & Updates
databaseEdition, locationId, name, project, cmekConfig, and tags.tags property is immutable and causes resource replacement when modified. To apply tags to an existing database without replacement, use the gcp.tags.TagValue resource instead.Encryption & Security
cmekConfig with your KMS key ID, create an IAM binding granting the Firestore service account (service-{project-number}@gcp-sa-firestore.iam.gserviceaccount.com) the roles/cloudkms.cryptoKeyEncrypterDecrypter role, and use dependsOn to ensure the IAM binding is created before the database.Point-in-Time Recovery
pointInTimeRecoveryEnablement is set to POINT_IN_TIME_RECOVERY_ENABLED, you get 7-day retention with reads supported on any timestamp within the past hour and 1-minute snapshots beyond 1 hour. When disabled (the default), you only get 1-hour retention. Use versionRetentionPeriod and earliestVersionTime to determine supported versions.