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 allocation, and backup scheduling and edition selection.
Spanner instances require a GCP project with the Spanner API enabled. Databases are created separately on the instance. The examples are intentionally small. Combine them with your own database resources and access controls.
Create a regional instance with node-based capacity
Most deployments start with a regional instance using node-based capacity for predictable compute and storage.
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 (e.g., “regional-us-central1”). The numNodes property sets capacity in full-node increments. The edition property determines feature availability and pricing tier. The defaultBackupScheduleType property controls whether new databases automatically get backup schedules; note that AUTOMATIC is not permitted for free instances.
Allocate capacity using processing units
For finer-grained capacity control, specify processing units directly instead of full nodes.
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 allows capacity allocation below full node increments (100 processing units equals one node). This provides more precise resource allocation and cost optimization. You cannot specify both numNodes and processingUnits; choose one capacity model.
Deploy across multiple regions for global availability
Applications serving global users 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
The config property uses a multi-regional value (e.g., “nam-eur-asia1”) that spans North America, Europe, and Asia. Multi-regional instances provide low-latency access to users across continents and higher availability through geographic redundancy. Capacity is still allocated using numNodes or processingUnits.
Beyond these examples
These snippets focus on specific instance-level features: regional and multi-regional placement, node-based and processing unit capacity models, and backup scheduling and edition selection. They’re intentionally minimal rather than full database deployments.
The examples rely on pre-existing infrastructure such as a GCP project with the Spanner API enabled. They focus on instance configuration rather than provisioning databases or access controls.
To keep things focused, common instance patterns are omitted, including:
- Autoscaling configuration (autoscalingConfig)
- Force destroy for instances with manual backups (forceDestroy)
- Free instance type configuration (instanceType)
- 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 & Immutability
config, name, and project properties are immutable and cannot be changed after instance creation. Changing these requires recreating the instance.regional-us-central1 or regional-europe-west1, or multi-regional configs like nam-eur-asia1. Consult the Configuration section of the docs for a complete list.name must be 6-30 characters long. If not provided, Pulumi auto-generates a name starting with tf-.Capacity & Scaling
numNodes for node-based sizing (e.g., numNodes: 2) or processingUnits for finer-grained control (e.g., processingUnits: 200). Choose one approach, not both.STANDARD, ENTERPRISE, or ENTERPRISE_PLUS based on your needs. Different editions provide different capabilities at different price points. Don’t configure edition for free instances.Free Instances
instanceType: "FREE_INSTANCE") cannot use automatic backups and should not have the edition field configured. Set defaultBackupScheduleType to NONE for free instances.Backups & Deletion
forceDestroy to true to delete all backups when deleting the instance. This is required if you created backups manually in the console.defaultBackupScheduleType to AUTOMATIC for automatic backups or NONE to disable default backups. Note that AUTOMATIC is not permitted for free instances.Labels & Resource Management
labels field is non-authoritative and only manages labels in your Pulumi configuration. Use the effectiveLabels output to see all labels present on the resource, including those added by other clients or services.regional-us-central1 for single-region instances, or multi-regional configs like nam-eur-asia1 for instances spanning multiple regions.