From 674d1398a9f3555d14601a75c10187f057581700 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 02:21:51 +0000 Subject: [PATCH] Document dynamic database credentials with connection functions Add section explaining Knex connection function pattern for short-lived credentials (AWS RDS IAM, GCP Cloud SQL, Vault rotation). Includes MySQL/MariaDB example with AWS RDS IAM auth, now supported as of v5.50.3. --- .../docs/cms/configurations/database.md | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/docusaurus/docs/cms/configurations/database.md b/docusaurus/docs/cms/configurations/database.md index 92f13a67e5..7461e98ec4 100644 --- a/docusaurus/docs/cms/configurations/database.md +++ b/docusaurus/docs/cms/configurations/database.md @@ -293,6 +293,97 @@ export default ({ env }) => ({ +## Dynamic database credentials + +Some cloud providers issue short-lived database credentials that expire after a fixed period. For example, AWS RDS IAM tokens are valid for 15 minutes; GCP Cloud SQL IAM tokens expire similarly; HashiCorp Vault can rotate secrets on a schedule. Using a static password in `.env` causes intermittent connection failures when the connection pool recycles idle connections after the token has expired. + +Strapi supports dynamic credentials through Knex's connection function pattern. Instead of a plain connection object, you can pass a synchronous or asynchronous function to `connection.connection`. Knex calls this function whenever it needs to open a new database connection, ensuring the pool always receives fresh credentials. This pattern works for PostgreSQL and MySQL/MariaDB. TypeScript types officially accept sync and async functions for `connection.connection` as of Strapi v5.50.3. + +:::tip +Include an `expirationChecker` property in the object returned by your function. Knex calls this before reusing a connection from the pool; if it returns `true`, Knex discards the existing connection and calls your function again to obtain fresh credentials. +::: + +### MySQL/MariaDB with AWS RDS IAM authentication + +The following example mints a fresh IAM auth token from the AWS SDK each time the pool opens a new MySQL connection. For a PostgreSQL equivalent, see the [PostgreSQL + AWS RDS IAM authentication example](#configuration-examples) in the configuration examples above. + + + + +```js title="./config/database.js" +const { Signer } = require('@aws-sdk/rds-signer'); + +module.exports = ({ env }) => { + const signer = new Signer({ + hostname: env('DATABASE_HOST', '127.0.0.1'), + port: env.int('DATABASE_PORT', 3306), + username: env('DATABASE_USERNAME', 'strapi'), + }); + + return { + connection: { + client: 'mysql', + connection: async () => { + const token = await signer.getAuthToken(); + const expiresAt = Date.now() + 15 * 60 * 1000; + + return { + host: env('DATABASE_HOST', '127.0.0.1'), + port: env.int('DATABASE_PORT', 3306), + database: env('DATABASE_NAME', 'strapi'), + user: env('DATABASE_USERNAME', 'strapi'), + password: token, + ssl: true, + expirationChecker: () => expiresAt - Date.now() <= 5 * 60 * 1000, + }; + }, + }, + }; +}; +``` + + + + +```ts title="./config/database.ts" +import { Signer } from '@aws-sdk/rds-signer'; + +export default ({ env }) => { + const signer = new Signer({ + hostname: env('DATABASE_HOST', '127.0.0.1'), + port: env.int('DATABASE_PORT', 3306), + username: env('DATABASE_USERNAME', 'strapi'), + }); + + return { + connection: { + client: 'mysql', + connection: async () => { + const token = await signer.getAuthToken(); + const expiresAt = Date.now() + 15 * 60 * 1000; + + return { + host: env('DATABASE_HOST', '127.0.0.1'), + port: env.int('DATABASE_PORT', 3306), + database: env('DATABASE_NAME', 'strapi'), + user: env('DATABASE_USERNAME', 'strapi'), + password: token, + ssl: true, + expirationChecker: () => expiresAt - Date.now() <= 5 * 60 * 1000, + }; + }, + }, + }; +}; +``` + + + + +:::note +AWS RDS IAM authentication requires SSL and IAM database authentication to be enabled on the RDS instance. Refer to the for the required certificate bundle and setup instructions. +::: + ## Configuration in database Configuration files are not multi-server friendly. To update configurations in production you can use a data store to get and set settings.