Docs / Managed databases

Managed databases

PostgreSQL or MariaDB that keeps running even if one server or one location goes down. It runs on your own servers, with any provider, and you only have to look after the database itself.

Concept: 2 data servers + 1 witness

A database cluster is made of three of your servers that are already connected to Saka:

RoleContentsJob
Data server 1Full databasePrimary or replica.
Data server 2Full databaseReplica or primary.
WitnessNo dataTakes part in electing the primary, so there are never two primaries when servers lose contact (no split data). Can be a small server.

Choose three different servers, ideally in three different locations (for example Singapore, Jakarta, and one more). The servers are linked through an encrypted private WireGuard network created by the agent. Each server's WireGuard private key is generated on that server and never leaves it.

Latency between your app and the database matters. Place your app close to one of the data locations. In testing, a TLS connection from Sydney to Bangalore took ±3.8 seconds, so Saka connection strings use connect_timeout=5.

PostgreSQL 17 or MariaDB 12.3

PostgreSQL 17MariaDB 12.3
TechnologyPatroni + etcdGalera + garbd (witness)
Best forNew appsWordPress, Laravel, PHP apps (MySQL-compatible)
WriterOne primary, one replicaThe first healthy data node becomes the writer, the other node is the standby writer
Replication modeAsynchronous or synchronous (your choice)Always synchronous
Port54323306
Initial userpostgresroot
TLSRequired (hostssl, SCRAM)Required (require_secure_transport)

A PostgreSQL cluster is usually ready in ±30 seconds to 5 minutes; MariaDB is built one node at a time (±1.5 minutes in testing). You are notified on Telegram when it is ready or if it fails.

Replication mode (PostgreSQL)

MariaDB Galera is always synchronous: every write is confirmed by both data locations before it completes.

Create a cluster

  1. Add at least three servers to Saka (see Getting started). All of them must be connected.
  2. Open Database, press + Buat klaster database (Create database cluster).
  3. Choose the engine, two data servers, one witness server, the replication mode, and a name (lowercase letters, numbers, hyphens, 3-31 characters, starting with a letter).
  4. Follow the creation steps on the detail page.

Connection string & password

The cluster detail page shows the connection string. The password is not shown automatically: press Tampilkan sandi (Show password). The password is read directly from your data server at that moment; Saka does not store it. The password is generated when the cluster is created, passed once to the data servers, and then forgotten by Saka.

PostgreSQL: multi-host connection string

The string includes both data locations. Drivers that support multiple hosts (libpq, JDBC, Go pgx) automatically connect to the primary:

.env
DATABASE_URL=postgresql://postgres:[email protected]:5432,198.51.100.20:5432/postgres?sslmode=require&target_session_attrs=read-write&connect_timeout=5

MariaDB: direct connection string

.env
DATABASE_URL=mysql://root:[email protected]:3306/?ssl=true

This direct string points to one node only. To have your app follow along when a server goes down, use the Saka proxy (below).

Proxy on your app server

PHP (mysqlnd) and Node.js (mysql2, node-postgres) drivers cannot switch to another address on their own. In testing, the PHP client kept trying the first address until it timed out, and the Node client hung without an error. That is why Saka provides Sambungkan server aplikasi (Connect app server):

PostgreSQL via proxy
DATABASE_URL=postgresql://postgres:[email protected]:5432/postgres?sslmode=require
MariaDB via proxy
DATABASE_URL=mysql://root:[email protected]:3306/?ssl=true

Examples used in testing (the MariaDB certificate is generated automatically, so certificate verification is turned off; the connection is still encrypted):

PHP (mysqli)
$m = mysqli_init();
$m->real_connect('127.0.0.1', 'root', $sandi, 'nama_db', 3306, null,
  MYSQLI_CLIENT_SSL | MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);
Node.js (mysql2)
mysql.createConnection({ host: '127.0.0.1', user: 'root', password: sandi,
  database: 'nama_db', ssl: { rejectUnauthorized: false } })
Laravel .env example
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nama_database_anda
DB_USERNAME=root
DB_PASSWORD=SANDI

TLS is required on both engines: the server rejects connections without TLS. The proxy passes connections through as they are, so turn on TLS in your driver (for example sslmode=require for PostgreSQL). Database certificates are generated on your own servers, not issued by a public CA.

The proxy can be removed from an app server at any time; the app on that server will then need a different connection string.

Fencing

The agent on each data server checks database health every 2 seconds. If a node is not fit to accept writes, its database port is closed to outside traffic with a TCP RST, so clients or the proxy immediately move to another node:

Traffic from the cluster's private network and from the server itself is not blocked.

Failover & self-healing

If the primary server goes down, the replica in another location takes over automatically. You are notified on Telegram when the primary moves, when no replica is in sync (the cluster temporarily cannot survive losing one server), and when a replica is in sync again.

Test (28 Sep 2026)Time until the app could write againRows lost
MariaDB, writer node killed suddenly, PHP and Node clients via proxy±11 seconds0
PostgreSQL product test, writer node killed suddenly, client via proxy33 seconds0
PostgreSQL proof of concept, asynchronous mode38.6 seconds0
PostgreSQL proof of concept, synchronous mode32.0 seconds0

The primary is elected among your own servers (etcd or garbd on all three servers). Saka Panel is not part of that path, so failover keeps working even if Saka Panel is down.

Delete a cluster

Delete it from the cluster detail page by typing the cluster name to confirm. All data in this database, in every location, is deleted and cannot be undone. The proxy on app servers is removed as well. A server that cannot be reached at that moment keeps the leftovers until that server is released.

Coming soon

Backups and point-in-time restore, database migration assisted by your AI agent, and automatic server creation through your cloud account.