The way back: move-back, repoint, disable¶
lokadb move-back: returning an organization to the cloud¶
lokadb move-back -db CLOUD_ADMIN -org 1 -customer CUSTOMER_ADMIN_DSN [-dry-run]
For the end of a contract, leaving BYOD, or a move to another database. It is the trigger-based move run in reverse:
- capture triggers are installed on the organization's tables in its database and log every change there — including foreign-key cascades and writes that bypass the cloud, which the cloud never sees;
- the tables are copied into unattached cloud partitions and the log is applied to them. Logical replication is not used in this direction (a subscription writes by table name, and the cloud table is the parent: rows would flow back to the customer through the foreign partition);
- the switch-over: first only this organization is paused while the log drains; then
ACCESS EXCLUSIVEon the cloud parents andEXCLUSIVEon the customer's tables (so direct writers there wait too), cloud first; the tail of the log; snapshots of both sides;DETACHof the foreign partition andATTACHof the cloud copy (nothing is scanned); row counts and row hashes are compared before any change — a difference cancels the switch and the organization stays in its database;COMMIT; - after the switch: a full comparison of the two snapshots (a mismatch names up to five tables and keys), foreign keys of the new partitions validated, the FDW server dropped;
__refscatch up with rows written in the customer database bypassing the cloud; if such a row's id belongs to another organization, nothing switches and the error names the id;- for 60 s (
-bridge) a view stands in for the old foreign table, so a proxy with stale metadata writes into the new partition, not into a database the cloud no longer reads; - the customer's tables stay with a comment "returned to the cloud by LokaDB at …"; LokaDB does not drop them (the command to do so is logged), and a later
move-orgof the same organization into the same database sets them aside in a schemalokadb_returned_<N>_<date>(or drops them with-drop-returned; see moving.md), while the customer's own tables of the same names are never touched; - without an administrative DSN (the role does not own the tables or cannot create the log schema), the copy runs under the organization's pause without triggers: slower, but the data comes back.
-dry-runsays which way it will take and how many rows.
The customer database is unavailable. move-back refuses and names the way out: LokaDB keeps no copy of a moved organization's rows. The customer restores the database from their backup, then lokadb repoint, then move-back (the loss is their backup's RPO). If the data is gone for good, move-back -abandon -confirm-org N returns the organization empty: its __refs rows are deleted with the foreign-key actions of cloud tables, with a loud warning.
lokadb repoint: a new database with the same rows¶
lokadb repoint -db CLOUD_ADMIN -org 1 -customer-app NEW_DSN -proxy-config lokadb.json
For a restore on another host, a failover to a replica, a new password.
- The new database is checked first: every foreign table has its table there with the same columns and types, made for this organization.
- Every other address the proxy uses for the organization (direct path, DDL replay — from the control plane, or from
customers_app/customersin the config) must lead to the same database:repointholds a random advisory lock on its connection to the new database and expects every other address to see it inpg_locks. A copy, a replica or another database of the same server does not. Credentials in the control plane are moved to the new host, port and database; config files are not edited — if an entry leads elsewhere,repointchanges nothing and names it. - The new database gets a new id in its table labels; the proxy refuses a database with a different id, so the old database is no longer used after
repoint. - TLS options of the FDW server come from the new DSN; options it does not have are removed.
ALTER SERVERandALTER USER MAPPINGhappen under the organization's pause; proxies reload credentials before their next statement. An ambiguousCOMMITis resolved by checking the cloud over a new connection.- No rows are copied. To move with the data from database A to database B:
move-back, thenmove-org.
lokadb disable: undoing enable¶
lokadb disable -db CLOUD_ADMIN -spec spec.json [-dry-run]
- One transaction under
ACCESS EXCLUSIVE. The tableenablestarted from,<table>__cloud, stays with its indexes, constraints and statistics; rows of other partitions (returned organizations, rows without an organization) are poured into it with triggers and foreign-key checks off. The pause grows with these rows;-dry-runcounts them. - What comes back: views, rules and functions that pointed at the parent; policies of other tables and functions over the row type; the application's triggers with their firing mode; privileges including column privileges; the application's own RLS (
FORCEtoo) and policies; foreign keys to__refspoint at the table again; the added organization column of child tables is dropped; identity and the original owner; index names. - Waiting for locks is bounded: a long reader does not hold
disable— and every statement behind it — forever. Each lock waits at most-lock-timeout(5 s), repeated-attempts(5) times; if the tables never free up,disablechanges nothing. - While any organization is in its own database,
disablerefuses:move-backeach first. __refsand thelokadbschema are dropped after-grace(60 s), while proxies with old metadata may still read them. If the application built something onlokadb.*afterenable(a view usinglokadb.org(), a default, a policy),disablenames it and leaves the schema rather than dropping it withCASCADE.- Open proxy sessions learn about
disableby notification (or within 30 s) and pass statements through as beforeenable, including statements prepared while the tables were enabled. - After
enable -preparewithoutenable,disableremoves what the preparation did.
The e2e stand runs move-back and disable under load for each application and checks that the rows equal those before the return and the schema equals the one before enable.