Docs Data and networking
Databases
Databases come from templates. Each one is a service with a persistent volume, a generated password and connection variables for your apps. A new database is private: it has no public address until you turn on its TCP proxy.
Add a database
- Dashboard: click Create, choose Database and pick PostgreSQL, MySQL, Redis or MongoDB. MariaDB is in Create → Template.
- Agent:
deploy_templatewithpostgres,mysql,mariadb,redisormongo. - CLI:
dawn add --database postgres(alsomysql,redis,mongo), ordawn add --template mariadb.
Then reference the connection URL from your app and deploy it:
DATABASE_URL=${{ Postgres.DATABASE_URL }}
Database templates
| Template | Service name | Image | Volume | Port |
|---|---|---|---|---|
postgres | Postgres | postgres:16 | /var/lib/postgresql/data | 5432 |
mysql | MySQL | mysql:8.4 | /var/lib/mysql | 3306 |
mariadb | MariaDB | mariadb:11 | /var/lib/mysql | 3306 |
redis | Redis | redis:7 | /data | 6379 |
mongo | MongoDB | mongo:7 | /data/db | 27017 |
Postgres starts with a 512 MB memory limit and Redis with 256 MB. MySQL, MariaDB and MongoDB get the plan’s default, 1 GB on Trial, 2 GB on Hobby and 4 GB on Pro. Change it under Settings → Deploy. All of them use the Always restart policy. Redis runs with a password and append-only persistence. Passwords are generated with ${{ secret(32) }} when the service is created. If a service with the same name already exists, the new one gets a suffix such as Postgres-2.
Variables
Use the private URL from your services. A *_PUBLIC_URL variable exists only while the database’s TCP proxy is on. It goes through the proxy, for tools outside Dawnrose.
| Database | Connection variables | Other variables |
|---|---|---|
| Postgres | DATABASE_URL, DATABASE_PUBLIC_URL | PGHOST, PGPORT, PGUSER (postgres), PGPASSWORD, PGDATABASE (dawnrose), PGDATA, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB |
| MySQL | MYSQL_URL, MYSQL_PUBLIC_URL | MYSQLHOST, MYSQLPORT, MYSQLUSER (root), MYSQLPASSWORD, MYSQLDATABASE, MYSQL_ROOT_PASSWORD, MYSQL_DATABASE (dawnrose) |
| MariaDB | MYSQL_URL, MYSQL_PUBLIC_URL | MYSQLHOST, MYSQLPORT, MYSQLUSER (root), MYSQLPASSWORD, MYSQLDATABASE, MYSQL_ROOT_PASSWORD, MARIADB_ROOT_PASSWORD, MARIADB_DATABASE (dawnrose) |
| Redis | REDIS_URL, REDIS_PUBLIC_URL | REDISHOST, REDISPORT, REDISUSER (default), REDISPASSWORD |
| MongoDB | MONGO_URL, MONGO_PUBLIC_URL | MONGOHOST, MONGOPORT, MONGOUSER (mongo), MONGOPASSWORD, MONGO_INITDB_ROOT_USERNAME, MONGO_INITDB_ROOT_PASSWORD |
The host variables hold the database’s private hostname, such as postgres.dawnrose.internal.
Volumes
A volume keeps data across deploys and restarts. Each database template attaches one at the path in the table above. You can add a volume to any service under Settings → Volume:
- A service has at most one volume, mounted at an absolute path such as
/data. Redeploy to mount a new volume. - The size counts against your plan’s volume storage. A volume can grow but not shrink.
- A service with a volume runs one replica, and its old deployment stops before the new one starts.
- To delete a volume, stop the service’s active deployment first. Deleting a volume or its service deletes the data permanently.
A template sizes its volumes from the volume storage your plan has left, up to 5 GB each.
Access from outside
A database starts private: only services in its environment can reach it. To connect from your machine or a tool outside Dawnrose, turn on its TCP proxy under Settings → Networking → TCP proxy, or have your agent call enable_tcp_proxy. That opens a public port on the Dawnrose edge that forwards to the database, and adds the database’s *_PUBLIC_URL variable, such as DATABASE_PUBLIC_URL or REDIS_PUBLIC_URL, with the address and credentials. Then open a shell with the database’s variables and use your usual client:
dawn shell --service Postgres
psql "$DATABASE_PUBLIC_URL"
To run a command inside the database’s container instead, use the Console tab or dawn exec:
dawn exec --service Postgres -- psql -c "select version()"
Click Disable next to the TCP proxy to close the public port. The *_PUBLIC_URL variable the proxy added is removed with it, unless you changed it.
A variable you wrote yourself that uses DAWNROSE_TCP_PROXY_* isn’t removed. Disabling the proxy names any that are left: change or delete them before the next deploy, or it fails on the missing reference.
Automatic schema setup
After an app’s first successful deploy, Dawnrose applies the schema your project already defines to the SQL database the app uses. This runs when the app’s variables reference exactly one Postgres, MySQL or MariaDB service, for example through ${{ Postgres.DATABASE_URL }}. It does not run for template apps or for the databases themselves.
Dawnrose tries these sources in order:
- Init scripts from docker-compose. If the database came from a compose stack whose file mounts
.sqlfiles into/docker-entrypoint-initdb.d, those files are applied, but only to an empty database. - The app’s migration tool. Dawnrose looks in the app’s container and runs the first tool it finds.
- A schema file. If no migration tool was found and nothing came from the compose file, Dawnrose applies the first schema file it finds, only to an empty database.
Steps 2 and 3 are skipped when the app has a pre-deploy command, since that is usually where migrations run.
| Found in the app | Command |
|---|---|
prisma/schema.prisma and prisma/migrations/ | npx prisma migrate deploy |
prisma/schema.prisma | npx prisma db push --skip-generate |
manage.py (Django) | python manage.py migrate --noinput |
artisan and database/migrations/ (Laravel) | php artisan migrate --force |
bin/rails and db/migrate/ | bin/rails db:prepare |
alembic.ini | alembic upgrade head |
knexfile.js or knexfile.ts, and migrations/ | npx knex migrate:latest |
drizzle.config.ts (or .js, .mjs, .cjs), and drizzle/ or migrations/ | npx drizzle-kit migrate |
drizzle.config.ts without a migrations folder | npx drizzle-kit push, only into an empty database |
For Drizzle apps, put drizzle-kit in dependencies, not devDependencies, so it is still in the image after the build prunes dev packages. drizzle-kit push builds tables straight from your schema; Dawnrose runs it only while the database is empty, so it can never drop data. Schema setup runs once, after the first deploy. For later changes, generate migrations with drizzle-kit generate and set the app’s pre-deploy command to npx drizzle-kit migrate, so they run before every deploy. To browse the data, deploy the Drizzle Studio template.
The npx commands use the tools installed in the app’s image; nothing is downloaded. The schema files Dawnrose looks for, in order, are ddl.sql, schema.sql, init.sql, database.sql, db.sql, db/schema.sql, db/init.sql, db/ddl.sql, sql/schema.sql, sql/init.sql, sql/ddl.sql, database/schema.sql and database/init.sql, relative to the app’s working directory. A schema file can be up to 140 KB. Lines that create or switch to another database (CREATE DATABASE, USE, \connect) are dropped, so the schema lands in the database the app uses. They are kept if one of the app’s variables has that database’s name as its value.
The result appears on the app’s Deployments tab (“Database ready”) and in the activity log. If setup fails, it is tried again on the next deploy.
Backups
The Backups tab appears on Postgres, MySQL, MariaDB and MongoDB services and on any service with a volume.
| Service | Backup |
|---|---|
| Postgres | pg_dump in custom format |
| MySQL, MariaDB | mysqldump of all databases, with routines and triggers |
| MongoDB | mongodump archive |
| Any other service with a volume, including Redis | A tarball of the volume |
Dumps run inside the service’s own container, so the service must be running. Each backup is encrypted with AES-256-GCM using a key specific to your workspace, then stored in the platform’s S3-compatible object storage.
Back up on demand or on a schedule
Click Back up now for a one-off backup. Turn on Scheduled backups to back up on a cron schedule in UTC; the default is 0 3 * * *, every day at 03:00 UTC. Click Save schedule to apply.
After each successful backup, older ones are deleted by a grandfather-father-son rotation set by four numbers:
- Last: how many of the newest backups to keep (default 3).
- Daily, Weekly, Monthly: keep the newest backup of each of that many recent days, weeks and months (defaults 7, 4 and 3).
The newest backup is never deleted.
Backups, both on demand and scheduled, need the Hobby or Pro plan. Stored backups count against a workspace total, 20 GB on Hobby and 100 GB on Pro, and are billed as volume storage. A failed backup sends a backup.failed notification.
Restore
Click Restore next to a successful backup and type the service name to confirm. The restore overwrites the service’s current data: Postgres with pg_restore --clean, MySQL and MariaDB by replaying the dump, MongoDB with mongorestore --drop, and volumes by replacing the volume’s contents. Restoring and deleting backups need the admin role.
Deleting a service keeps its backups for 7 days. In that time the workspace owner can restore one into a new service of the same kind.
Agents use list_backups, create_backup, configure_backups and restore_backup; the last one requires confirm: true.