Deploy Azure SQL Databases

The azure-native:sql:Database resource, part of the Pulumi Azure Native provider, defines an Azure SQL Database: its compute tier, creation mode, and storage configuration. This guide focuses on five capabilities: basic provisioning, SKU selection, database copy and restore, geo-replication, and backup redundancy.

Databases belong to Azure SQL servers and may reference source databases for copy or restore operations. The examples are intentionally small. Combine them with your own server infrastructure, networking, and security configuration.

Create a database with minimal configuration

Most deployments start by specifying only the essential properties: name, location, resource group, and server.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    databaseName: "testdb",
    location: "southeastasia",
    resourceGroupName: "Default-SQL-SouthEastAsia",
    serverName: "testsvr",
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    database_name="testdb",
    location="southeastasia",
    resource_group_name="Default-SQL-SouthEastAsia",
    server_name="testsvr")
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			DatabaseName:      pulumi.String("testdb"),
			Location:          pulumi.String("southeastasia"),
			ResourceGroupName: pulumi.String("Default-SQL-SouthEastAsia"),
			ServerName:        pulumi.String("testsvr"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        DatabaseName = "testdb",
        Location = "southeastasia",
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        ServerName = "testsvr",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.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()
            .databaseName("testdb")
            .location("southeastasia")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .serverName("testsvr")
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      databaseName: testdb
      location: southeastasia
      resourceGroupName: Default-SQL-SouthEastAsia
      serverName: testsvr

The databaseName, location, resourceGroupName, and serverName properties are required. Without an explicit sku, Azure assigns a default tier (typically General Purpose). The database uses default collation, size limits, and backup settings.

Specify compute tier using service objective

VCore-based databases let you control compute capacity by specifying a service objective abbreviation (like BC for Business Critical) along with hardware generation and core count.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    databaseName: "testdb",
    location: "southeastasia",
    resourceGroupName: "Default-SQL-SouthEastAsia",
    serverName: "testsvr",
    sku: {
        capacity: 2,
        family: "Gen4",
        name: "BC",
    },
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    database_name="testdb",
    location="southeastasia",
    resource_group_name="Default-SQL-SouthEastAsia",
    server_name="testsvr",
    sku={
        "capacity": 2,
        "family": "Gen4",
        "name": "BC",
    })
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			DatabaseName:      pulumi.String("testdb"),
			Location:          pulumi.String("southeastasia"),
			ResourceGroupName: pulumi.String("Default-SQL-SouthEastAsia"),
			ServerName:        pulumi.String("testsvr"),
			Sku: &sql.SkuArgs{
				Capacity: pulumi.Int(2),
				Family:   pulumi.String("Gen4"),
				Name:     pulumi.String("BC"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        DatabaseName = "testdb",
        Location = "southeastasia",
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        ServerName = "testsvr",
        Sku = new AzureNative.Sql.Inputs.SkuArgs
        {
            Capacity = 2,
            Family = "Gen4",
            Name = "BC",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.DatabaseArgs;
import com.pulumi.azurenative.sql.inputs.SkuArgs;
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()
            .databaseName("testdb")
            .location("southeastasia")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .serverName("testsvr")
            .sku(SkuArgs.builder()
                .capacity(2)
                .family("Gen4")
                .name("BC")
                .build())
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      databaseName: testdb
      location: southeastasia
      resourceGroupName: Default-SQL-SouthEastAsia
      serverName: testsvr
      sku:
        capacity: 2
        family: Gen4
        name: BC

The sku property defines compute resources. The name field uses a tier abbreviation (BC for Business Critical), family specifies hardware generation (Gen4), and capacity sets vCore count. This configuration provides predictable performance for production workloads.

Copy an existing database to a new database

Database copies create transactionally consistent snapshots, useful for testing or creating point-in-time backups.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    createMode: azure_native.sql.CreateMode.Copy,
    databaseName: "dbcopy",
    location: "southeastasia",
    resourceGroupName: "Default-SQL-SouthEastAsia",
    serverName: "testsvr",
    sku: {
        name: "S0",
        tier: "Standard",
    },
    sourceDatabaseId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb",
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    create_mode=azure_native.sql.CreateMode.COPY,
    database_name="dbcopy",
    location="southeastasia",
    resource_group_name="Default-SQL-SouthEastAsia",
    server_name="testsvr",
    sku={
        "name": "S0",
        "tier": "Standard",
    },
    source_database_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb")
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			CreateMode:        pulumi.String(sql.CreateModeCopy),
			DatabaseName:      pulumi.String("dbcopy"),
			Location:          pulumi.String("southeastasia"),
			ResourceGroupName: pulumi.String("Default-SQL-SouthEastAsia"),
			ServerName:        pulumi.String("testsvr"),
			Sku: &sql.SkuArgs{
				Name: pulumi.String("S0"),
				Tier: pulumi.String("Standard"),
			},
			SourceDatabaseId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        CreateMode = AzureNative.Sql.CreateMode.Copy,
        DatabaseName = "dbcopy",
        Location = "southeastasia",
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        ServerName = "testsvr",
        Sku = new AzureNative.Sql.Inputs.SkuArgs
        {
            Name = "S0",
            Tier = "Standard",
        },
        SourceDatabaseId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.DatabaseArgs;
import com.pulumi.azurenative.sql.inputs.SkuArgs;
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()
            .createMode("Copy")
            .databaseName("dbcopy")
            .location("southeastasia")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .serverName("testsvr")
            .sku(SkuArgs.builder()
                .name("S0")
                .tier("Standard")
                .build())
            .sourceDatabaseId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb")
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      createMode: Copy
      databaseName: dbcopy
      location: southeastasia
      resourceGroupName: Default-SQL-SouthEastAsia
      serverName: testsvr
      sku:
        name: S0
        tier: Standard
      sourceDatabaseId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SouthEastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb

When createMode is Copy, the sourceDatabaseId points to the database to clone. The copy operation creates a new database with the same schema and data. The sku property can differ from the source, allowing you to copy a production database to a smaller tier for development.

Restore a database to a specific point in time

Point-in-time restore recovers a database to any moment within its retention period, enabling recovery from accidental changes.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    createMode: azure_native.sql.CreateMode.PointInTimeRestore,
    databaseName: "dbpitr",
    location: "southeastasia",
    resourceGroupName: "Default-SQL-SouthEastAsia",
    restorePointInTime: "2020-10-22T05:35:31.503Z",
    serverName: "testsvr",
    sourceDatabaseId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb",
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    create_mode=azure_native.sql.CreateMode.POINT_IN_TIME_RESTORE,
    database_name="dbpitr",
    location="southeastasia",
    resource_group_name="Default-SQL-SouthEastAsia",
    restore_point_in_time="2020-10-22T05:35:31.503Z",
    server_name="testsvr",
    source_database_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb")
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			CreateMode:         pulumi.String(sql.CreateModePointInTimeRestore),
			DatabaseName:       pulumi.String("dbpitr"),
			Location:           pulumi.String("southeastasia"),
			ResourceGroupName:  pulumi.String("Default-SQL-SouthEastAsia"),
			RestorePointInTime: pulumi.String("2020-10-22T05:35:31.503Z"),
			ServerName:         pulumi.String("testsvr"),
			SourceDatabaseId:   pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        CreateMode = AzureNative.Sql.CreateMode.PointInTimeRestore,
        DatabaseName = "dbpitr",
        Location = "southeastasia",
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        RestorePointInTime = "2020-10-22T05:35:31.503Z",
        ServerName = "testsvr",
        SourceDatabaseId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.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()
            .createMode("PointInTimeRestore")
            .databaseName("dbpitr")
            .location("southeastasia")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .restorePointInTime("2020-10-22T05:35:31.503Z")
            .serverName("testsvr")
            .sourceDatabaseId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb")
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      createMode: PointInTimeRestore
      databaseName: dbpitr
      location: southeastasia
      resourceGroupName: Default-SQL-SouthEastAsia
      restorePointInTime: 2020-10-22T05:35:31.503Z
      serverName: testsvr
      sourceDatabaseId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-SoutheastAsia/providers/Microsoft.Sql/servers/testsvr/databases/testdb

When createMode is PointInTimeRestore, the restorePointInTime specifies the target timestamp (ISO8601 format). The sourceDatabaseId identifies the database to restore from. Azure uses automatic backups to reconstruct the database state at the specified time.

Configure geo-replication with online secondary

Geo-replicated secondaries provide disaster recovery by continuously replicating data to a different region.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    createMode: azure_native.sql.CreateMode.Secondary,
    databaseName: "testdb",
    location: "southeastasia",
    resourceGroupName: "Default-SQL-SouthEastAsia",
    secondaryType: azure_native.sql.SecondaryType.Geo,
    serverName: "testsvr",
    sku: {
        name: "S0",
        tier: "Standard",
    },
    sourceDatabaseId: "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb",
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    create_mode=azure_native.sql.CreateMode.SECONDARY,
    database_name="testdb",
    location="southeastasia",
    resource_group_name="Default-SQL-SouthEastAsia",
    secondary_type=azure_native.sql.SecondaryType.GEO,
    server_name="testsvr",
    sku={
        "name": "S0",
        "tier": "Standard",
    },
    source_database_id="/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb")
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			CreateMode:        pulumi.String(sql.CreateModeSecondary),
			DatabaseName:      pulumi.String("testdb"),
			Location:          pulumi.String("southeastasia"),
			ResourceGroupName: pulumi.String("Default-SQL-SouthEastAsia"),
			SecondaryType:     pulumi.String(sql.SecondaryTypeGeo),
			ServerName:        pulumi.String("testsvr"),
			Sku: &sql.SkuArgs{
				Name: pulumi.String("S0"),
				Tier: pulumi.String("Standard"),
			},
			SourceDatabaseId: pulumi.String("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        CreateMode = AzureNative.Sql.CreateMode.Secondary,
        DatabaseName = "testdb",
        Location = "southeastasia",
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        SecondaryType = AzureNative.Sql.SecondaryType.Geo,
        ServerName = "testsvr",
        Sku = new AzureNative.Sql.Inputs.SkuArgs
        {
            Name = "S0",
            Tier = "Standard",
        },
        SourceDatabaseId = "/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.DatabaseArgs;
import com.pulumi.azurenative.sql.inputs.SkuArgs;
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()
            .createMode("Secondary")
            .databaseName("testdb")
            .location("southeastasia")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .secondaryType("Geo")
            .serverName("testsvr")
            .sku(SkuArgs.builder()
                .name("S0")
                .tier("Standard")
                .build())
            .sourceDatabaseId("/subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb")
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      createMode: Secondary
      databaseName: testdb
      location: southeastasia
      resourceGroupName: Default-SQL-SouthEastAsia
      secondaryType: Geo
      serverName: testsvr
      sku:
        name: S0
        tier: Standard
      sourceDatabaseId: /subscriptions/00000000-1111-2222-3333-444444444444/resourceGroups/Default-SQL-NorthEurope/providers/Microsoft.Sql/servers/testsvr1/databases/testdb

When createMode is Secondary and secondaryType is Geo, the database becomes a readable replica in a different region. The sourceDatabaseId points to the primary database. The location must differ from the primary’s region. If the primary region fails, you can promote the secondary to become the new primary.

Configure backup storage redundancy

Backup storage redundancy controls how database backups are replicated, affecting both durability and cost.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const database = new azure_native.sql.Database("database", {
    databaseName: "testdb",
    location: "southeastasia",
    requestedBackupStorageRedundancy: azure_native.sql.BackupStorageRedundancy.Zone,
    resourceGroupName: "Default-SQL-SouthEastAsia",
    serverName: "testsvr",
});
import pulumi
import pulumi_azure_native as azure_native

database = azure_native.sql.Database("database",
    database_name="testdb",
    location="southeastasia",
    requested_backup_storage_redundancy=azure_native.sql.BackupStorageRedundancy.ZONE,
    resource_group_name="Default-SQL-SouthEastAsia",
    server_name="testsvr")
package main

import (
	sql "github.com/pulumi/pulumi-azure-native-sdk/sql/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := sql.NewDatabase(ctx, "database", &sql.DatabaseArgs{
			DatabaseName:                     pulumi.String("testdb"),
			Location:                         pulumi.String("southeastasia"),
			RequestedBackupStorageRedundancy: pulumi.String(sql.BackupStorageRedundancyZone),
			ResourceGroupName:                pulumi.String("Default-SQL-SouthEastAsia"),
			ServerName:                       pulumi.String("testsvr"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var database = new AzureNative.Sql.Database("database", new()
    {
        DatabaseName = "testdb",
        Location = "southeastasia",
        RequestedBackupStorageRedundancy = AzureNative.Sql.BackupStorageRedundancy.Zone,
        ResourceGroupName = "Default-SQL-SouthEastAsia",
        ServerName = "testsvr",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.sql.Database;
import com.pulumi.azurenative.sql.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()
            .databaseName("testdb")
            .location("southeastasia")
            .requestedBackupStorageRedundancy("Zone")
            .resourceGroupName("Default-SQL-SouthEastAsia")
            .serverName("testsvr")
            .build());

    }
}
resources:
  database:
    type: azure-native:sql:Database
    properties:
      databaseName: testdb
      location: southeastasia
      requestedBackupStorageRedundancy: Zone
      resourceGroupName: Default-SQL-SouthEastAsia
      serverName: testsvr

The requestedBackupStorageRedundancy property sets the replication strategy for backups. Zone-redundant storage replicates backups across availability zones within a region, providing protection against zone failures. Other options include local (single zone) and geo-redundant (cross-region) storage.

Beyond these examples

These snippets focus on specific database-level features: SKU configuration and compute tiers, database creation modes, and backup storage redundancy. They’re intentionally minimal rather than full database deployments.

The examples reference pre-existing infrastructure such as Azure SQL servers, source databases for copy/restore operations, and resource groups and subscriptions. They focus on configuring the database rather than provisioning the surrounding infrastructure.

To keep things focused, common database patterns are omitted, including:

  • Elastic pool assignment (elasticPoolId)
  • Collation and character set configuration
  • Maximum database size limits (maxSizeBytes)
  • High availability replica counts
  • Maintenance windows and update schedules
  • Encryption and Always Encrypted enclaves

These omissions are intentional: the goal is to illustrate how each database feature is wired, not provide drop-in production modules. See the Azure SQL Database resource reference for all available configuration options.

Let's deploy Azure SQL Databases

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Database Creation & Modes
What are the different ways to create a database?

You can create a database using different createMode values:

  • Default - Create a new empty database
  • Copy - Copy an existing database (requires sourceDatabaseId)
  • Secondary - Create a secondary replica (requires sourceDatabaseId and secondaryType)
  • PointInTimeRestore - Restore to a specific point in time (requires sourceDatabaseId and restorePointInTime)
  • Recovery - Restore from geo-backup (requires sourceResourceId)
  • Restore - Restore a dropped database (requires sourceResourceId)
  • RestoreLongTermRetentionBackup - Restore from long-term retention vault

Note: Copy, Secondary, and RestoreLongTermRetentionBackup aren’t supported for DataWarehouse edition.

How do I specify the database SKU and performance tier?
Configure the sku property with the tier name (e.g., ‘S0’, ‘BC_Gen4’, ‘HS_Gen4’). You can specify just the name, or include capacity and family for more control (e.g., name=‘BC’, capacity=2, family=‘Gen4’).
What properties can't be changed after database creation?

The following properties are immutable:

  • location - Database region
  • createMode - Creation method
  • collation - Database collation
  • catalogCollation - Metadata catalog collation
  • isLedgerOn - Ledger database setting

Plan these settings carefully at creation time.

Restore & Recovery
How do I restore a database?

You have several restore options:

Point-in-time restore: Set createMode to ‘PointInTimeRestore’, provide sourceDatabaseId, and specify restorePointInTime in ISO8601 format.

Geo-backup restore: Set createMode to ‘Recovery’ and provide sourceResourceId pointing to the recoverable database.

Dropped database restore: Set createMode to ‘Restore’ and provide sourceResourceId pointing to the restorable dropped database.

For cross-subscription restores, use sourceResourceId instead of sourceDatabaseId. Cross-tenant restores require the ‘x-ms-authorization-auxiliary’ header with authentication token for the source tenant.

How do I copy an existing database?
Set createMode to ‘Copy’ and provide the sourceDatabaseId of the source database. The copy will be created in the same region unless you specify a different location.
High Availability & Replication
What's the difference between Geo, Named, and Standby secondary replicas?

When creating a secondary replica (createMode='Secondary'), you specify the secondaryType:

  • Geo - Online geo-replication for disaster recovery (readable secondary in different region)
  • Standby - Standby replica for high availability (same region)
  • Named - Named replica for Hyperscale databases (readable secondary with independent scaling)
How do I configure zone redundancy for my database?
Set zoneRedundant to true to spread database replicas across multiple availability zones. You can also pin a database to a specific zone using availabilityZone (e.g., ‘1’).
Performance & Scaling
How do I control the cutover when scaling to Hyperscale?
When scaling from Business Critical, General Purpose, Premium, or Standard tier to Hyperscale, set manualCutover to true to pause the operation and wait for your input. Later, trigger the cutover by setting performCutover to true when the scaling operation is in waiting state.
How do I configure auto-pause for serverless databases?
Set autoPauseDelay to the number of minutes of inactivity before auto-pause. Use -1 to disable automatic pause. Also configure minCapacity to set the minimum compute allocated when not paused.
Security & Encryption
What are the Always Encrypted enclave types?
Set preferredEnclaveType to either ‘Default’ or ‘VBS’ (Virtualization-Based Security). VBS enclaves provide additional security isolation for Always Encrypted operations.
How do I enable ledger on a database?
Set isLedgerOn to true at creation time to make all tables in the database ledger tables. This property cannot be changed after the database is created.
Backup & Maintenance
How do I configure backup storage redundancy?
Set requestedBackupStorageRedundancy to your desired redundancy level (e.g., ‘Zone’, ‘Geo’, ‘Local’). This determines how database backups are replicated.
How do I specify a maintenance window?
Set maintenanceConfigurationId to the resource ID of your desired maintenance configuration (e.g., ‘/subscriptions/…/publicMaintenanceConfigurations/SQL_SouthEastAsia_1’).
Limitations & Gotchas
Can I use free monthly limits on multiple databases?
No, only one database per subscription can have useFreeLimit set to true. Configure freeLimitExhaustionBehavior to control what happens when limits are exhausted (AutoPause or BillForUsage).

Using a different cloud?

Explore database guides for other cloud providers: