Skip to main content

Configuring Plugin Databases

This guide covers a variety of production persistence use cases which are supported out of the box by Backstage. The database manager allows the developer to set the client and database connection details on a per plugin basis in addition to the base client and connection configuration. This means that you can use a SQLite 3 in-memory database for a specific plugin whilst using PostgreSQL for everything else and so on.

By default, Backstage uses automatically created databases for each plugin whose names follow the backstage_plugin_<pluginId> pattern, e.g. backstage_plugin_auth. You can configure a different database name prefix for use cases where you have multiple deployments running on a shared database instance or cluster.

With infrastructure defined as code or data (Terraform, AWS CloudFormation, etc.), you may have database credentials which lack permissions to create new databases or you do not have control over the database names. In these instances, you can set the database connection configuration on a per plugin basis.

Backstage supports all of these use cases with the DatabaseManager provided by @backstage/backend-common. We will now cover how to use and configure Backstage's databases.

Prerequisites

Dependencies

Please ensure the appropriate database drivers are installed in your backend package. If you intend to use both PostgreSQL and SQLite, you can install both of them.

# From your Backstage root directory
# install pg if you need PostgreSQL
yarn --cwd packages/backend add pg

# install SQLite 3 if you intend to set it as the client
yarn --cwd packages/backend add better-sqlite3

From an operational perspective, you only need to install drivers for clients that are actively used.

Configuration

You should set the base database client and connection information in your app-config.yaml (or equivalent) file. The base client and configuration is used as the default which is extended for each plugin with the same or unset client type. If a client type is specified for a specific plugin which does not match the base client, the configuration set for the plugin will be used as is without extending the base configuration.

Client type and configuration for plugins need to be defined under backend.database.plugin.<pluginId>. As an example, catalog is the pluginId for the catalog plugin and any configuration defined under that block is specific to that plugin. We will now explore more detailed example configurations below.

Minimal In-Memory Configuration

In the example below, we are using better-sqlite3 in-memory databases for all plugins. You may want to use this configuration for testing or other non-durable use cases.

backend:
database:
client: better-sqlite3
connection: ':memory:'

PostgreSQL

The example below uses PostgreSQL (pg) as the database client for all plugins. The auth plugin uses a user defined database name instead of the automatically generated one which would have been backstage_plugin_auth.

backend:
database:
client: pg
connection:
host: some.example-pg-instance.tld
user: postgres
password: password
port: 5432
plugin:
auth:
connection:
database: pg_auth_set_by_user

Custom Database Name Prefix

The configuration below uses example_prefix_ as the database name prefix instead of backstage_plugin_. Plugins such as auth and catalog will use databases named example_prefix_auth and example_prefix_catalog respectively.

backend:
database:
client: pg
connection:
host: some.example-pg-instance.tld
user: postgres
password: password
port: 5432
prefix: 'example_prefix_'

Connection Configuration Per Plugin

Both auth and catalog use connection configuration with different credentials and database names. This type of configuration can be useful for environments with infrastructure as code or data which may provide randomly generated credentials and/or database names.

backend:
database:
client: pg
connection: 'postgresql://some.example-pg-instance.tld:5432'
plugin:
auth:
connection: 'postgresql://fort:knox@some.example-pg-instance.tld:5432/unwitting_fox_jumps'
catalog:
connection: 'postgresql://bank:reserve@some.example-pg-instance.tld:5432/shuffle_ransack_playback'

PostgreSQL and SQLite 3

The example below uses PostgreSQL (pg) as the database client for all plugins except the auth plugin which uses better-sqlite3. As the auth plugin's client type is different from the base client type, the connection configuration for auth is used verbatim without extending the base configuration for PostgreSQL.

backend:
database:
client: pg
connection: 'postgresql://foo:bar@some.example-pg-instance.tld:5432'
plugin:
auth:
client: better-sqlite3
connection: ':memory:'

Check Your Databases

The DatabaseManager will attempt to create the databases if they do not exist. If you have set credentials per plugin because the credentials in the base configuration do not have permissions to create databases, you must ensure they exist before starting the service. The service will not be able to create them, it can only use them.

Privileges

As Backstage attempts to check if the database exists, you may need to grant privileges to list or show databases for a given user. For PostgreSQL, you would grant the following:

GRANT SELECT ON pg_database TO some_user;

MySQL:

GRANT SHOW DATABASES ON *.* TO some_user;

The mechanisms in this guide should help you tackle different database deployment situations. Good luck!