Skip to content

Providers

Providers are the services that you can use in your app.

A provider is the infrastructure service that you can use in your app. It’s listed in your sst.config.ts under providers.

sst.config.ts
{
providers: {
aws: true
}
}

Install

To add a provider to your app run.

Terminal window
sst add <provider>

This command adds the provider to your config, installs the packages, and adds the namespace of the provider to your globals.

You can add multiple providers to your app.

{
providers: {
aws: true,
cloudflare: true
}
}

The name of a provider comes from the URL of the provider in the Pulumi Registry. For example, https://www.pulumi.com/registry/packages/aws/ is the URL of the AWS Classic provider. So the name of the provider here is aws.

Learn more about the sst add command.


Configure

You can configure a provider in your sst.config.ts. For example, to change the region for AWS.

{
providers: {
aws: {
region: "us-west-2"
}
}
}

You can check out the available list of options that you can configure for a provider over on the Pulumi docs. For example, here are the ones for AWS and Cloudflare.


Versions

In addition to these options, you can also pass in the version of the provider you want to use. By default, SST uses the latest version.

{
providers: {
aws: {
version: "6.27.0"
}
}
}

Credentials

Most providers will read your credentials from the environment. For example, for Cloudflare you might set your token like so.

Terminal window
export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa

However, some providers also allow you to pass in the credentials through the config.

{
providers: {
cloudflare: {
apiToken: "aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa"
}
}
}

Learn more about configuring providers.


Components

There are two types of components in your app.

  1. Native SST components, namespaced under sst.*
  2. And Pulumi components, namespaced under <provider>.*

The sst add command injects the provider into the globals of your config.

For example, running sst add aws will allow you to use all the components under the aws namepsace.

new aws.s3.BucketV2("b", {
bucket: "mybucket",
tags: {
Name: "My bucket"
}
});

Here we are using the BucketV2 component from the AWS Classic provider.


Functions

Aside from the components, there are a collection of functions that are exposed by a provider. These are listed in the Pulumi docs as getXXXXXX on the sidebar.

For example, to get the AWS account being used in your app.

const current = await aws.getCallerIdentity({});
const accountId = current.accountId;
const callerArn = current.arn;
const callerUser = current.userId;

Or to get the current region.

const current = await aws.getRegion({});
const region = current.name;

Output versions

The above are async methods that return promises. That means that if you call these in your app, they’ll block the deployment of any resources that are defined after it.

So we instead recommend using the Output version of these functions. For example, if we wanted to set the above as environment variables in a function, we would do something like this

new sst.aws.Function("MyFunction, {
handler: "src/lambda.handler",
environment: {
ACCOUNT: aws.getCallerIdentityOutput({}).accountId,
REGION: aws.getRegionOutput().name
}
}

The aws.getXXXXOutput functions typically return an object of type Output<primitive>. Learn more about Outputs.


State

You app generates some state that is uploaded to your provider. This includes:

  1. A state file for your resources. This is a JSON file.
  2. A passphrase that is used to encrypt the secrets in your state.

We’ll look at how the state works in detail below but to do store it SST creates:

  1. A bucket to store the state, typically named sst-state-<hash>. This is created in the region of your home. More on this below.
  2. An SSM parameter to store the passphrase used to encrypt your secrets, under /sst/passphrase/<app>/<stage>. Also created in the region of your home.

The passphrase is used to encrypt any secrets and sensitive information. Without it SST won’t be able to read the state file and deploy your app.


Home

Your sst.config.ts specifies which provider to use for storing your state. We call this the home of your app.

{
home: "aws"
}

You can specify which provider you’d like to use for this. Currently aws and cloudflare are supported.

When you specify your home provider, SST assumes you’d like to use that provider in your app as well and adds it to your providers internally. So the above is equivalent to doing this.

{
home: "aws",
providers: {
aws: true
}
}

This also means that if you change the region of the aws provider above, you are changing the region for your home as well.

You can read more about the home provider in Config.


Bootstrap

As SST starts deploying the resources in your app, it creates some additional bootstrap resources. If your app has a Lambda function or a Docker container, then SST will create the following in the same region as the given resource:

  1. An assets bucket to store the function packages, typically named sst-asset-<hash>.
  2. An ECR repository to store container images, called sst-asset.
  3. An SSM parameter to store the assets bucket name and the ECR repository, stored under /sst/bootstrap.

The SSM parameter is used to look up the location of these resources.

When you remove an SST app, it does not remove the state or bootstrap resources. This is because it does not know if there are other apps that might be using this. So if you want to completely remove any SST created resources, you’ll need to manually remove these in the regions you’ve deployed to.


How state works

The state file is a JSON representation of all the low level resources created by your app. It is a cached version of the state of resources in the cloud provider.

So when you do a deploy the following happens.

  1. The components in the sst.config.ts get converted into low level resource definitions. These get compared to the the state file.
  2. The differences between the two are turned into API calls that are made to your cloud provider.
    • If there’s a new resource, it gets created.
    • If a resource has been removed, it gets removed.
    • If there’s a change in config of the resource, it gets applied.
  3. The state file is updated to reflected the new state of these resources. Now the sst.config.ts, the state file, and the resources in the cloud provider are all in sync.

Going out of sync

This process works fine till you manually go change these resources through the cloud provider’s console. This will cause the state and the resources to not be in sync anymore. This can cause an issue in some cases.

Let’s look at a couple of scenarios.

Say we’ve deployed a Function with it set to { timeout: 10 seconds" }. At this point, the config, state, and resource are in sync.


Change the resource
  • We now go change the timeout to 20 seconds in the AWS Console.
    • The config and state are out of sync with the resource since they are still set to 10 seconds.
  • Now if we deploy our app, the config will be comapred to the state.
    • It’ll find no differences and so it won’t update the resource.

The config and state will stay out of sync with the resource.


Change the config
  • If we change our config to { timeout: 30 seconds" } and do a deploy.
  • The config and state will have some differences.
  • SST will make a call to AWS to set the timeout of the resource to 30 seconds.
    • Once updated, it’ll update the state file to match the current state of the resource.

The config, state, and resource are back being in sync.


Remove the resource
  • Next we go to the AWS Console and remove the function.
    • The config and state still have the function with the timeout set to 30 seconds.
  • If we change our config to { timeout: 60 seconds } and do a deploy.
  • The config and state will be different.
  • SST will make a call to update the timeout of the resource to 60 seconds.
    • But this call to AWS will fail because the function doesn’t exist.

Your deploys will fail moving forward because the your state shows that a resource exists but it doesn’t anymore. To fix this, you’ll need to refresh your state file.


Refresh the state

To fix scenarios where the resources in the cloud are out of sync with the state of your app, you’ll need to run.

Terminal window
sst refresh

This command does a couple of simple things:

  1. It goes through every single resource in your state.
  2. Makes a call to the cloud provider to check the resource.
    • If the configs are different, it’ll update the state to reflect the change.
    • If the resource doesn’t exist anymore, it’ll remove it from the state.

Now the state and the resources are in sync. So if we take the scenario from above where we removed the function from the AWS Console but not from our config or state. To fix it, we’ll need to:

  • Run sst refresh
    • This will remove the function from the state as well.
  • Now if we change our config to { timeout: 60 seconds } and do a deploy.
  • The config and state will be compared and it’ll find that a function with that config doesn’t exist.
  • So SST will make a call to AWS to create a new function with the given config.

In general we do not recommend manually changing resources in a cloud provider since it puts your state out of sync. But if you find yourself in a situation where this happens, you can use the sst refresh command to put them back in sync.


Multiple providers

Aside from the providers that are listed in the providers in your config, you can create your own providers. This is useful for multi-region or multi-account deployments.

const useast1 = new aws.Provider("AnotherAWS");

Multi-region

You might want to create multiple providers in cases where some resources in your app need to go to one region, while others need to go to a separate region.

Let’s look at an example. Assume your app is normally deployed to us-west-1. But you need to create an ACM certificate that needs to be deployed to us-east-1.

const useast1 = new aws.Provider("useast1", { region: "us-east-1" });
new sst.aws.Function("MyFunction, "src/lambda.handler");
new aws.acm.Certificate("cert", {
domainName: "foo.com",
validationMethod: "EMAIL",
}, { provider: useast1 });

Here the function is created in your default region, us-west-1. While the certificate is created in us-east-1.