Managed MariaDB
Managed MariaDB is a MariaDB container that Temps runs on your own server: you create the service, link it to a project, and Temps injects DATABASE_URL, MYSQL_URL and MARIADB_URL into that project's environment. It speaks the MySQL wire protocol, so MySQL clients and ORMs connect unchanged. The default mariadb:lts image is backed up with mariadb-backup and archived binary logs, which gives you point-in-time recovery. There are no per-GB fees or connection caps.
MariaDB is opt-in. Installing or starting Temps does not pull or run a MariaDB container until you create a service that uses one, and Temps keeps its own data in PostgreSQL. Provision it from the dashboard, the @temps-sdk/cli command-line tool (Manage from the CLI), or the REST API.
Creating a MariaDB instance
Create a MariaDB instance
- 1
Navigate to Services then click Create Service.
- 2
Select MariaDB.
- 3
Keep the default image (mariadb:lts) and choose a size profile: small (default), standard or dedicated. The size profile cannot be changed after creation.
- 4
Click Create Service. Temps auto-assigns a host port starting from 3306, creates a data volume mounted at /var/lib/mysql, and generates the app and root passwords.
Checkpoint: Confirm the new service appears in the Services list and its status shows running before linking it.
Via Dashboard:
- Navigate to Services → Create Service.
- Select MariaDB.
- Keep the default image,
mariadb:lts, or enter another MariaDB image. - Pick a size profile. You choose it once: it is not editable after creation.
- Click Create Service.
On creation Temps auto-assigns a host port starting from 3306, creates a Docker volume mounted at /var/lib/mysql, and generates the application and root passwords. The container is named mariadb-<service-name>, runs with the server timezone set to UTC, and has binary logging on from the first start so the service is ready for point-in-time recovery.
| Parameter | Default | Editable after creation |
|---|---|---|
port | Auto-assigned from 3306 | Yes |
docker_image | mariadb:lts | Yes |
binlog_archive_interval | 5m (1m, 5m, 15m or 60m) | Yes |
size_profile | small (small, standard or dedicated) | No |
database | app | No |
username | app | No |
password | Auto-generated | No |
root_password | Auto-generated | No |
Manage from the CLI
The same services commands cover every managed database. If you use an AI coding agent, install the temps-cli skill and describe what you want; the agent runs these commands for you.
Create
# Log in once (stores credentials in ~/.temps)
bunx @temps-sdk/cli login
# Create the service. Set parameters with repeatable -s key=value flags
bunx @temps-sdk/cli services create -t mariadb -n my-db -y
# A larger profile and a one-minute binlog shipping interval
bunx @temps-sdk/cli services create -t mariadb -n my-db \
-s size_profile=standard -s binlog_archive_interval=1m -y
Inspect, link & manage
# List services and grab the numeric ID
bunx @temps-sdk/cli services list
# Full details, including the connection parameters
bunx @temps-sdk/cli services show --id 10
# Link to a project so DATABASE_URL (and friends) are injected on deploy
bunx @temps-sdk/cli services link --id 10 -p my-app
bunx @temps-sdk/cli services env --id 10 -p my-app # see injected vars
bunx @temps-sdk/cli services unlink --id 10 -p my-app
# Lifecycle
bunx @temps-sdk/cli services stop --id 10
bunx @temps-sdk/cli services start --id 10
bunx @temps-sdk/cli services remove --id 10 -f # removes container and data volume
To bring a MariaDB or MySQL-compatible container you already run under Temps management, see Import an existing container.
Connecting to MariaDB
Link MariaDB to a project
- 1
Open the project, go to its Databases page and link the MariaDB service.
- 2
Trigger a deploy of the linked project to pick up the injected variables.
Checkpoint: Run services env to confirm DATABASE_URL, MYSQL_URL and MARIADB_URL are present for the project before relying on them in code.
A MariaDB service is one shared database server. When you link it, Temps creates a separate database for each project and environment inside that server, named {project_slug}_{environment_slug}, and injects these variables on the next deploy:
| Variable | Value |
|---|---|
DATABASE_URL, MYSQL_URL, MARIADB_URL | The same mysql://user:password@host:3306/database connection string |
MYSQL_HOST, MARIADB_HOST | The container name, reachable over the internal Docker network |
MYSQL_PORT, MARIADB_PORT | 3306 |
MYSQL_DATABASE, MARIADB_DATABASE | The per-project, per-environment database |
MYSQL_USER, MARIADB_USER | The service's application user |
MYSQL_PASSWORD, MARIADB_PASSWORD | Its generated password |
MariaDB is the one managed engine that injects DATABASE_URL. PostgreSQL injects POSTGRES_URL instead, so check the variable name if you move an app between the two. Only one service of each type can be linked to a project.
Node.js with mysql2
import mysql from 'mysql2/promise';
// DATABASE_URL is injected automatically when the service is linked
const pool = mysql.createPool(process.env.DATABASE_URL);
const [rows] = await pool.query('SELECT NOW() AS now');
Python with SQLAlchemy
import os
from sqlalchemy import create_engine, text
# Swap the scheme for the driver you installed (PyMySQL here)
url = os.environ["DATABASE_URL"].replace("mysql://", "mysql+pymysql://", 1)
engine = create_engine(url, pool_pre_ping=True)
with engine.connect() as conn:
print(conn.execute(text("SELECT NOW()")).scalar())
Size profiles
The size profile sets both the container's resource limits and MariaDB's own tuning, so the buffer pool always fits inside the memory cap. Pick it when you create the service.
| Profile | Memory cap | CPU cap | InnoDB buffer pool | max_connections | Use it for |
|---|---|---|---|---|---|
small (default) | 512 MiB (+256 MiB swap) | 0.75 cores | 128 MiB | 50 | A shared server with 4 or 8 GB of RAM |
standard | 1024 MiB (+512 MiB swap) | 1.5 cores | 384 MiB | 100 | A host with more spare memory |
dedicated | None | None | 1024 MiB | 200 | A host dedicated to this database |
Every linked project shares that connection budget, so size your application pools against max_connections. You can still change the container's memory, swap and CPU caps afterwards from the service's Resources card, as for any managed service (see Resource limits); the MariaDB tuning that came with the profile stays as it was.
Backups & point-in-time recovery
Backups go to an S3-compatible bucket on a schedule you configure. See Backups for S3 sources, schedules and retention. For MariaDB, Temps picks the method from the tools in the image:
| Image has | Backup method | Point-in-time recovery |
|---|---|---|
mariadb-backup and mariadb-binlog (the default mariadb:lts does) | Physical base backup, streamed with mariadb-backup and gzipped | Yes |
| Neither | Logical dump with mariadb-dump --single-transaction | No |
Point-in-time recovery has two halves:
- A physical base backup. Each scheduled run uploads a
mariadb-backupsnapshot and records the binary-log position it was taken at. - Archived binary logs. Between backups, Temps ships closed binary-log segments to the same S3 location every
binlog_archive_interval(5 minutes by default). A restore replays them on top of the base withmariadb-binlog.
Binary logs are only shipped once a backup schedule covers the service, because the schedule is where Temps learns which S3 bucket to use. A MariaDB service with no schedule has no point-in-time recovery. The most you can lose on a restore is one archive interval of writes, so lower binlog_archive_interval to 1m if five minutes is too much.
Use InnoDB tables. MyISAM and Aria tables are not crash-safe and do not restore consistently to a point in time.
Restoring
Restore MariaDB to a point in time
- 1
Open the MariaDB service in the dashboard and go to its Backups.
- 2
Check which restore modes the service supports. Point-in-time recovery needs a mariadb-backup physical backup; a mariadb-dump backup restores only as a whole.
Checkpoint: Run bunx @temps-sdk/cli services restore-capabilities --id 10 to confirm before restoring.
- 3
Pick the backup to restore from and, for point-in-time recovery, set the target timestamp in UTC.
- 4
Start the restore, in place or into a new service.
Checkpoint: Watch the restore run until it completes with bunx @temps-sdk/cli services restore-runs --id 10.
MariaDB supports all three restore modes:
- In place overwrites the service's data with the backup.
- Into a new service leaves the original untouched and creates a second MariaDB service from the backup, which is the safe way to inspect old data or build a staging copy.
- Point in time restores a physical base backup and replays binary logs up to your target. The target is a UTC timestamp, or a
binlog_file:positionpair. Transaction-ID and named-restore-point targets are PostgreSQL only.
Restore via the Temps CLI
# Inspect what restore modes a service supports (in-place / new service / PITR)
bunx @temps-sdk/cli services restore-capabilities --id <id>
# List backups stored on an S3 source
bunx @temps-sdk/cli services list-backups --s3-source-id <id>
# Start a restore (optionally to a point in time, optionally into a new service)
bunx @temps-sdk/cli services restore --id <id> --backup-id <id> [--pitr <iso>] [--new-service auto]
A point-in-time restore from a mariadb-dump backup is rejected, because a logical dump has no binary-log position to replay from. Restore & Recovery covers the restore plan preview, recovery targets and restoring backups made by another Temps instance.
Changing the MariaDB version
docker_image is editable, so you move to another MariaDB release by changing the image on the service. The container runs with MARIADB_AUTO_UPGRADE=1, which makes MariaDB upgrade its system tables on the first start after an image change. Take a backup first. To rehearse on a copy, restore that backup into a new service and try the new image there before you touch the original.
The services upgrade command, and the guided major-version upgrade that PostgreSQL has, are not available for MariaDB.
Security
- Name
Network Isolation- Description
- Apps connect over the internal Docker network, using the container name as the host
- The host port Temps assigns is bound to
127.0.0.1, so the database is not reachable from the internet - Credentials are auto-generated at creation; you never have to choose a password
- Name
Credential Handling- Description
- Temps injects credentials as environment variables when the service is linked, so never hard-code them
- Passwords are encrypted with AES-256-GCM before they are written to the Temps database
- Passwords are fixed at creation; there is no credential rotation for managed services yet
Database contents are not encrypted at the application layer. For encryption at rest, use encrypted volumes or LUKS on the host; Temps does not manage disk encryption.
Deleting the service
Delete the MariaDB service
- 1
Take a fresh backup first: open Services, select the service, click Trigger backup and wait for it to finish.
- 2
Unlink all projects so no running app still holds a reference to the credentials.
- 3
Delete the service from its settings page and confirm.
Checkpoint: Confirm the service no longer appears in the Services list. Deletion removes the container, data volume and backup records and cannot be undone.
Deleting removes the container, volume and backup records; backup objects remain in your S3 bucket and can be recovered with orphan restore. The live data on the volume cannot be recovered.
Pricing & ownership
Because the service runs on your own infrastructure, there are no per-GB charges, connection caps or metered bandwidth fees: the cost is the server it runs on. Your data never leaves that server, and Temps (the company) has no access to it. See Data Ownership & Privacy for the full policy, including GDPR.
Related
- Set Up Managed Services — every service type, import and per-project isolation
- Managed PostgreSQL, Managed Redis, Managed MongoDB and Managed S3 (RustFS) — the other managed engines
- Backups and Restore & Recovery — schedules, S3 sources, restore modes and recovery targets
- Environment variables — how injected variables reach your app