Skip to main content
CYPEX Documentation
Support
v2.0.0 Latest stable release View changelog ->

Rollback constraints

4 min read

The v2.0.0 migrations are forward-only. There is no automatic rollback script. This page documents what you can and cannot undo if you need to revert the upgrade.

What you can roll back

Disable RLS on tenant-scoped tables

For every table that had RLS enabled by the v2.0.0 upgrade:

1
2
3
ALTER TABLE cypex.t_ui DISABLE ROW LEVEL SECURITY;
ALTER TABLE cypex.t_file DISABLE ROW LEVEL SECURITY;
-- ... repeat for every tenant-scoped table

Disabling RLS reverts the visibility filtering. Combined with restoring the previous permission grants, this restores v1.x row visibility.

Drop the new organization_id columns

1
2
3
ALTER TABLE cypex.t_ui DROP COLUMN organization_id;
ALTER TABLE cypex.t_file DROP COLUMN organization_id;
-- ... repeat for every tenant-scoped table

This is safe only if no application code reads the column. Once you cut traffic on the v2.0.0 backend, the backend will start selecting and inserting the column. Rolling it back at that point breaks the backend.

Delete the Default Organization and mappings

1
2
3
DELETE FROM cypex.t_role_organization;
DELETE FROM cypex.t_module_organization;
DELETE FROM cypex.t_organization WHERE organization_domain = 'default';

This drops the new mappings but leaves the new tables in place. See the “Cannot roll back” list below for whether the tables themselves can be removed.

What you cannot easily roll back

The password policy

The default password policy is inserted with ON CONFLICT DO NOTHING, and the value is a JSON blob. There is no automatic “remove” path:

  • Removing the row from cypex.t_config does not break the upgrade, but the backend will then apply no password complexity check at all (which is more permissive than the default).
  • If you inserted a custom policy before the upgrade, rolling back means restoring the previous cypex.t_config row from your backup.

New tables if app code references them

The new tables (t_organization, t_module_organization, t_role_organization, t_permission_audit_log) cannot be dropped if any application code references them. After the v2.0.0 backend has started, the backend will reference them on every request. Drop them only if you also revert the backend binary to v1.x.

Data written with organization_id set

Once the v2.0.0 backend has served requests and new rows have been written with organization_id populated, rolling back the schema loses the organization context for those rows. They will still be visible (because RLS can be disabled and the column can be dropped), but the organization-scoped logic is gone.

The recommendation: do not write new rows if you plan to roll back. Either:

  • Hold traffic on the v1.x backend until you decide, or
  • Switch the v2.0.0 backend into maintenance mode before the first user-facing request.

New JWT claims in already-issued tokens

The v2.0.0 backend issues JWTs with the new claims. If users still hold those tokens after a rollback, the v1.x backend will reject them as malformed. The fix is to invalidate all sessions (force logout) before the rollback, or wait for natural token expiry.

cypex_user privilege changes

Revoking write privileges from cypex_user is straightforward to undo (GRANT INSERT, UPDATE, DELETE ON ... TO cypex_user;), but doing so on production without coordination is risky. Plan this as part of the rollback, not as an ad-hoc fix.

  1. Decide the rollback trigger before the upgrade window. Which failure modes cause you to roll back versus fix forward?
  2. Hold traffic as soon as the decision to roll back is made. Either stop the backend or switch it to maintenance mode.
  3. Restore the database from the pre-upgrade pg_dump backup. This is the cleanest rollback path. The schema changes are not reversible cleanly enough that a partial rollback is usually worthwhile.
  4. Restore the backend to the previous version.
  5. Invalidate all sessions by restarting the backend with a fresh JWT signing key, or by waiting for natural token expiry.
  6. Communicate the rollback to users and stakeholders.

Test rollback on staging first

The recommendation in Pre-upgrade checklist applies here: rehearse the rollback on a staging replica before doing it on production. The rollback timing is dominated by the database restore, not by the schema changes themselves.

Summary

ChangeRollback cost
RLS enabled on tablesEasy: ALTER TABLE ... DISABLE
organization_id columnsEasy if no new data written
New mappingsEasy: DELETE
Default password policyManual: restore from backup
New tablesHard: depends on app code
New JWTs in flightHard: force logout
cypex_user privilege changesEasy but disruptive