This page is about features available in the Shuttle Pro Tier.

This plugin provisions databases on AWS RDS using Shuttle. The following engines are supported:

  • Postgres
  • MySql
  • MariaDB

RDS vs Shared DB

  • Dedicated Instance: Each instance of AWS RDS is it’s own dedicated instance.
  • Stability and Security: AWS RDS has greater stability due to it being a service directly offered by AWS, and also greater security due to being a dedicated instance.
  • Flexible: AWS RDS instances on the Shuttle platform can be customised to suit your needs. Instance size can be increased from the default and AWS RDS features can be enabled or disabled.

On AWS RDS we offer:

  • MariaDB
  • MySQL
  • Postgres

With the Shared DB we offer:

  • MongoDB
  • Postgres

Default RDS Instance

The RDS instance created by Shuttle has the following specifications and features by default:

  • 2 vCPU
  • 1 GB Memory
  • 20 GiB Storage
  • Backups Disabled
  • Single Availability Zone
  • 1 Node
  • No Proxy

The pricing of this instance can be found in the Pro Add-ons section of the pricing page.

If you require a different configuration, please contact us on Discord or email us at hello@shuttle.rs. We can provision any size or configuration of RDS to suit your needs - a full list of RDS features can be found here

Shuttle makes sure that any data stored in your provisioned database is stored permanently and will persist if you redeploy your server via cargo shuttle deploy, as well as if you restart your service via cargo shuttle project restart.

Usage

Add shuttle-aws-rds to the dependencies for your service. Each type of database is behind the following feature flag and attribute path. *-rustls feature enables rustls-based implementation, otherwise some flavour of native-tls is used.

EngineFeature flagsAttribute pathReturn type
Postgrespostgres or postgres-rustlsshuttle_aws_rds::Postgressqlx::PgPool
MySqlmysql or mysql-rustlsshuttle_aws_rds::MySqlsqlx::MySqlPool
MariaDBmariadb or mariadb-rustlsshuttle_aws_rds::MariaDBsqlx::MySqlPool

Parameters

ParameterTypeDefaultDescription
local_uristrNoneIf specified, on local runs, connect to this database instead of starting a Docker container for it.

When setting the local_uri you can also insert secrets from Secrets.toml using string interpolation. To insert the PASSWORD secret, pass it in like this:

#[shuttle_runtime::main]
async fn tide(
    #[shuttle_aws_rds::Postgres(
        local_uri = "postgres://postgres:{secrets.PASSWORD}@localhost:16695/postgres"
    )] pool: PgPool,
) -> ShuttleTide<MyState> { ... }
If you are interpolating a secret from Secrets.dev.toml, you need to set the same secret in Secrets.toml to a empty string so that this step does not crash in deployment.

The URI should be formatted according to the Postgres or MySql and MariaDB documentation, depending on which one you’re using.

If you do not specify a local_uri, then cargo-shuttle will attempt to spin up a Docker container and launch the database inside of it. For this to succeed, you must have Docker installed and you must also have started the Docker engine. If you have not used Docker before, the easiest way is to install the desktop app and then launch it in order to start the Docker engine.

Connection string

After deploying a project with a database macro, you can view the connection string with credentials with:

cargo shuttle resource list --show-secrets

Using the connection string, you can connect to it for manual querying, inspection, and migration. You can also export/import data using a dump tool suitable for the database of choice.

Example

This snippet shows the main function of a tide app that uses the shuttle_aws_rds::Postgres attribute to provision an RDS Postgres database. It gives you an authenticated sqlx Pool, which you can use to interact with the database.

main.rs
#[shuttle_runtime::main]
async fn tide(#[shuttle_aws_rds::Postgres] pool: PgPool) -> ShuttleTide<MyState> {
    pool.execute(include_str!("../schema.sql"))
        .await
        .map_err(CustomError::new)?;

    let state = MyState { pool };
    let mut app = tide::with_state(state);

    app.with(tide::log::LogMiddleware::new());
    app.at("/todo").post(add);
    app.at("/todo/:id").get(retrieve);

    Ok(app.into())
}

The full example can be found on GitHub.