The gcp:spanner/instance:Instance resource, part of the Pulumi GCP provider, provisions a Cloud Spanner instance: an isolated set of compute and storage resources that hosts databases. This guide focuses on three capabilities: regional and multi-regional placement, node-based vs processing-unit capacity models, and edition selection and backup scheduling.
Spanner instances require a GCP project with the Spanner API enabled. The examples are intentionally small. Combine them with your own database definitions and access controls.
Provision a regional instance with fixed node count
Most deployments start with a regional instance that uses a fixed number of nodes for predictable capacity and cost.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const example = new gcp.spanner.Instance("example", {
config: "regional-us-central1",
displayName: "Test Spanner Instance",
numNodes: 2,
edition: "STANDARD",
defaultBackupScheduleType: "AUTOMATIC",
labels: {
foo: "bar",
},
});
import pulumi
import pulumi_gcp as gcp
example = gcp.spanner.Instance("example",
config="regional-us-central1",
display_name="Test Spanner Instance",
num_nodes=2,
edition="STANDARD",
default_backup_schedule_type="AUTOMATIC",
labels={
"foo": "bar",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/spanner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := spanner.NewInstance(ctx, "example", &spanner.InstanceArgs{
Config: pulumi.String("regional-us-central1"),
DisplayName: pulumi.String("Test Spanner Instance"),
NumNodes: pulumi.Int(2),
Edition: pulumi.String("STANDARD"),
DefaultBackupScheduleType: pulumi.String("AUTOMATIC"),
Labels: pulumi.StringMap{
"foo": pulumi.String("bar"),
},
})
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 example = new Gcp.Spanner.Instance("example", new()
{
Config = "regional-us-central1",
DisplayName = "Test Spanner Instance",
NumNodes = 2,
Edition = "STANDARD",
DefaultBackupScheduleType = "AUTOMATIC",
Labels =
{
{ "foo", "bar" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.spanner.Instance;
import com.pulumi.gcp.spanner.InstanceArgs;
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 example = new Instance("example", InstanceArgs.builder()
.config("regional-us-central1")
.displayName("Test Spanner Instance")
.numNodes(2)
.edition("STANDARD")
.defaultBackupScheduleType("AUTOMATIC")
.labels(Map.of("foo", "bar"))
.build());
}
}
resources:
example:
type: gcp:spanner:Instance
properties:
config: regional-us-central1
displayName: Test Spanner Instance
numNodes: 2
edition: STANDARD
defaultBackupScheduleType: AUTOMATIC
labels:
foo: bar
The config property defines geographic placement and replication strategy. Regional configurations like “regional-us-central1” store data in a single region with automatic zone replication. The numNodes property sets compute capacity; each node provides 1000 processing units. The edition property determines feature availability and pricing tier (STANDARD, ENTERPRISE, or ENTERPRISE_PLUS). The defaultBackupScheduleType controls whether new databases automatically create backup schedules; AUTOMATIC is not permitted for free instances.
Allocate capacity using processing units
Processing units provide finer-grained capacity control than nodes, allowing you to provision compute in increments of 100 processing units.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const example = new gcp.spanner.Instance("example", {
config: "regional-us-central1",
displayName: "Test Spanner Instance",
processingUnits: 200,
labels: {
foo: "bar",
},
});
import pulumi
import pulumi_gcp as gcp
example = gcp.spanner.Instance("example",
config="regional-us-central1",
display_name="Test Spanner Instance",
processing_units=200,
labels={
"foo": "bar",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/spanner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := spanner.NewInstance(ctx, "example", &spanner.InstanceArgs{
Config: pulumi.String("regional-us-central1"),
DisplayName: pulumi.String("Test Spanner Instance"),
ProcessingUnits: pulumi.Int(200),
Labels: pulumi.StringMap{
"foo": pulumi.String("bar"),
},
})
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 example = new Gcp.Spanner.Instance("example", new()
{
Config = "regional-us-central1",
DisplayName = "Test Spanner Instance",
ProcessingUnits = 200,
Labels =
{
{ "foo", "bar" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.spanner.Instance;
import com.pulumi.gcp.spanner.InstanceArgs;
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 example = new Instance("example", InstanceArgs.builder()
.config("regional-us-central1")
.displayName("Test Spanner Instance")
.processingUnits(200)
.labels(Map.of("foo", "bar"))
.build());
}
}
resources:
example:
type: gcp:spanner:Instance
properties:
config: regional-us-central1
displayName: Test Spanner Instance
processingUnits: 200
labels:
foo: bar
The processingUnits property replaces numNodes for sub-node granularity. One node equals 1000 processing units, so this example provisions 0.2 nodes worth of capacity. You must specify exactly one of numNodes, processingUnits, or autoscalingConfig (except for FREE_INSTANCE types).
Deploy across multiple continents for global access
Applications serving users worldwide benefit from multi-regional instances that replicate data across continents.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const example = new gcp.spanner.Instance("example", {
config: "nam-eur-asia1",
displayName: "Multi Regional Instance",
numNodes: 2,
labels: {
foo: "bar",
},
});
import pulumi
import pulumi_gcp as gcp
example = gcp.spanner.Instance("example",
config="nam-eur-asia1",
display_name="Multi Regional Instance",
num_nodes=2,
labels={
"foo": "bar",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/spanner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := spanner.NewInstance(ctx, "example", &spanner.InstanceArgs{
Config: pulumi.String("nam-eur-asia1"),
DisplayName: pulumi.String("Multi Regional Instance"),
NumNodes: pulumi.Int(2),
Labels: pulumi.StringMap{
"foo": pulumi.String("bar"),
},
})
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 example = new Gcp.Spanner.Instance("example", new()
{
Config = "nam-eur-asia1",
DisplayName = "Multi Regional Instance",
NumNodes = 2,
Labels =
{
{ "foo", "bar" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.spanner.Instance;
import com.pulumi.gcp.spanner.InstanceArgs;
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 example = new Instance("example", InstanceArgs.builder()
.config("nam-eur-asia1")
.displayName("Multi Regional Instance")
.numNodes(2)
.labels(Map.of("foo", "bar"))
.build());
}
}
resources:
example:
type: gcp:spanner:Instance
properties:
config: nam-eur-asia1
displayName: Multi Regional Instance
numNodes: 2
labels:
foo: bar
Multi-regional configurations like “nam-eur-asia1” span North America, Europe, and Asia. Spanner automatically replicates data across these regions, reducing read latency for geographically distributed clients. Write latency increases compared to regional instances due to cross-region consensus requirements.
Beyond these examples
These snippets focus on specific instance-level features: regional and multi-regional placement, node-based and processing-unit capacity models, and edition selection and backup scheduling. They’re intentionally minimal rather than full database deployments.
The examples assume pre-existing infrastructure such as a GCP project with Spanner API enabled. They focus on configuring the instance rather than provisioning databases or access controls.
To keep things focused, common instance patterns are omitted, including:
- Autoscaling configuration (autoscalingConfig)
- Free instance tier (instanceType: FREE_INSTANCE)
- Force destroy for backup cleanup (forceDestroy)
- Custom labels beyond basic examples
These omissions are intentional: the goal is to illustrate how each instance feature is wired, not provide drop-in database modules. See the Spanner Instance resource reference for all available configuration options.
Let's create GCP Cloud Spanner Instances
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Instance Configuration & Capacity
numNodes for node-based allocation, processingUnits for granular control (e.g., 200 units), or autoscalingConfig for automatic scaling. Free instances don’t require any of these.autoscalingConfig is enabled, numNodes and processingUnits become read-only output fields that reflect current capacity.config determines geographic placement and replication. Use regional values like regional-us-central1 for single regions, or multi-regional values like nam-eur-asia1 for broader coverage.STANDARD, ENTERPRISE, and ENTERPRISE_PLUS editions, each with different capabilities and pricing. Don’t set edition for free instances.Free Instance Limitations
instanceType = FREE_INSTANCE) cannot use automatic backups, cannot configure the edition field, and don’t require capacity settings (numNodes, processingUnits, or autoscalingConfig).Immutability & Lifecycle
config, name, and project properties are immutable. Changing them requires recreating the instance.forceDestroy to true to delete the instance and its backups.Labels & Metadata
labels field is non-authoritative, meaning Pulumi only manages labels in your configuration. Use effectiveLabels to see all labels on the resource.name must be 6-30 characters. If not provided, a random name starting with tf- is generated. The displayName must be 4-30 characters and unique per project.defaultBackupScheduleType to AUTOMATIC for new databases. However, automatic backups aren’t permitted for free instances.