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:
| Role | Contents | Job |
|---|---|---|
| Data server 1 | Full database | Primary or replica. |
| Data server 2 | Full database | Replica or primary. |
| Witness | No data | Takes 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 17 | MariaDB 12.3 | |
|---|---|---|
| Technology | Patroni + etcd | Galera + garbd (witness) |
| Best for | New apps | WordPress, Laravel, PHP apps (MySQL-compatible) |
| Writer | One primary, one replica | The first healthy data node becomes the writer, the other node is the standby writer |
| Replication mode | Asynchronous or synchronous (your choice) | Always synchronous |
| Port | 5432 | 3306 |
| Initial user | postgres | root |
| TLS | Required (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)
- Fast (asynchronous): writes as fast as a single server. If the primary dies suddenly, the last few seconds of transactions may be lost.
- No data loss (synchronous): every write waits for the second location. Slower by about one network round trip between locations (±38 ms between Singapore and Bangalore in testing). Good for money transactions.
MariaDB Galera is always synchronous: every write is confirmed by both data locations before it completes.
Create a cluster
- Add at least three servers to Saka (see Getting started). All of them must be connected.
- Open Database, press + Buat klaster database (Create database cluster).
- 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).
- 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:
DATABASE_URL=postgresql://postgres:[email protected]:5432,198.51.100.20:5432/postgres?sslmode=require&target_session_attrs=read-write&connect_timeout=5MariaDB: direct connection string
DATABASE_URL=mysql://root:[email protected]:3306/?ssl=trueThis 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):
- Saka installs a small HAProxy on the server where your app runs (a server registered with Saka that is not a member of the cluster).
- The proxy listens on
127.0.0.1and forwards to a healthy data node. The other node is the backup. - Your app just connects to
127.0.0.1. The port is the same as the database port (5432 or 3306), or that port plus 10000 (15432 or 13306) if a local database already uses it.
DATABASE_URL=postgresql://postgres:[email protected]:5432/postgres?sslmode=requireDATABASE_URL=mysql://root:[email protected]:3306/?ssl=trueExamples used in testing (the MariaDB certificate is generated automatically, so certificate verification is turned off; the connection is still encrypted):
$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);mysql.createConnection({ host: '127.0.0.1', user: 'root', password: sandi,
database: 'nama_db', ssl: { rejectUnauthorized: false } })DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nama_database_anda
DB_USERNAME=root
DB_PASSWORD=SANDITLS 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:
- PostgreSQL: only the Patroni leader is open, replicas are closed.
- MariaDB: open only when the node is Primary and Synced. A node that is rejoining stays closed until it is in sync.
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 again | Rows lost |
|---|---|---|
| MariaDB, writer node killed suddenly, PHP and Node clients via proxy | ±11 seconds | 0 |
| PostgreSQL product test, writer node killed suddenly, client via proxy | 33 seconds | 0 |
| PostgreSQL proof of concept, asynchronous mode | 38.6 seconds | 0 |
| PostgreSQL proof of concept, synchronous mode | 32.0 seconds | 0 |
- PostgreSQL: a server that went down comes back as a replica by itself when it is turned on (pg_rewind), with no manual steps.
- MariaDB: a server that went down copies data from another node when it comes back, then becomes a writer again.
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.
Backups and point-in-time restore, database migration assisted by your AI agent, and automatic server creation through your cloud account.