Change an Organization's Tier from Trial to Enterprise
This page is for operators of a self-hosted Permit Platform whose organization still shows the Trial tier. It explains how the installer sets the tier, how to check that the installer did it, and how to change the tier in the PostgreSQL database by hand.
How the installer sets the tier
The migrations job, permit-migrations, sets every organization to Enterprise tier each time the installer runs, on first installation and on every upgrade. The job sets both tier fields:
is_enterprise = trueusage_limits.billing_tier = "enterprise"
In most installations, no manual change is needed. To confirm that the job updated your organizations, search its logs while the job still exists in the namespace:
Enterprise tier applied to <N> organization(s)means the update ran.Enterprise tier update skipped: <error>means the update failed and the job continued. Fix the error, or change the tier manually as described in Change the tier manually.
Run kubectl logs -n permit-platform job/permit-migrations | grep -i "enterprise tier" to find these messages.
Tier fields in the database
The organization's tier is stored in two columns of the v2.v2_organization table. Update both columns to change the tier.
| Column | Type | Controls |
|---|---|---|
is_enterprise | boolean | Enterprise feature access and the tier badge |
usage_limits.billing_tier | string inside a JSONB object | Billing status and the trial countdown message |
Prerequisites
kubectlaccess to the namespace where Permit Platform runs. The commands use the default namespace,permit-platform.- A running PostgreSQL pod in that namespace.
- A recent database backup. See Create backups.
Change the tier manually
Use this procedure when the migrations job didn't update an organization, for example because the update was skipped or the installation predates the automatic update.
1. Find the PostgreSQL pod
List the pods and copy the name of the postgres pod:
kubectl get pods -n permit-platform | grep postgres
The output looks like this:
postgres-c94f7f6fd-tj55t 1/1 Running 0 2d
2. Check the organization's current tier
Replace <postgres-pod-name> with the pod name and <org-name> with the organization name:
kubectl exec -n permit-platform <postgres-pod-name> -- \
psql -U permit -d permit -c \
"SELECT id, name, is_enterprise, usage_limits FROM v2.v2_organization WHERE name = '<org-name>';"
Example output:
id | name | is_enterprise | usage_limits
--------------------------------------+----------+---------------+-------------------------------------------------------
8cdcc192-0ba3-472f-8691-87d765af715f | gke-test | f | {"mau": 5000, "tenants": 50, "billing_tier": "trial"}
The organization is on Trial tier when is_enterprise is f (false) and usage_limits contains "billing_tier": "trial". Copy the id value for the next step.
3. Set the organization to Enterprise tier
Update both fields in one statement. Replace <organization-uuid> with the id from the previous step:
kubectl exec -n permit-platform <postgres-pod-name> -- \
psql -U permit -d permit -c \
"UPDATE v2.v2_organization
SET is_enterprise = true,
usage_limits = jsonb_set(usage_limits, '{billing_tier}', '\"enterprise\"')
WHERE id = '<organization-uuid>';"
For example:
kubectl exec -n permit-platform postgres-c94f7f6fd-tj55t -- \
psql -U permit -d permit -c \
"UPDATE v2.v2_organization
SET is_enterprise = true,
usage_limits = jsonb_set(usage_limits, '{billing_tier}', '\"enterprise\"')
WHERE id = '8cdcc192-0ba3-472f-8691-87d765af715f';"
PostgreSQL confirms that one row changed:
UPDATE 1
UPDATE 0 means no organization has that id. Check the value and run the statement again.
4. Verify the change in the database
Run the query from step 2 again:
kubectl exec -n permit-platform <postgres-pod-name> -- \
psql -U permit -d permit -c \
"SELECT id, name, is_enterprise, usage_limits FROM v2.v2_organization WHERE name = '<org-name>';"
Expected output:
id | name | is_enterprise | usage_limits
--------------------------------------+----------+---------------+------------------------------------------------------------
8cdcc192-0ba3-472f-8691-87d765af715f | gke-test | t | {"mau": 5000, "tenants": 50, "billing_tier": "enterprise"}
The change is saved when is_enterprise is t (true) and usage_limits contains "billing_tier": "enterprise".
5. Verify the change in the Permit frontend
Hard refresh the Permit frontend in your browser. The tier badge shows Enterprise, and the trial countdown message is gone. If the page still shows the Trial tier, see Changes not visible in the frontend.
Set the PRO tier instead
To set an organization to PRO tier, set is_enterprise to false and billing_tier to "pro":
kubectl exec -n permit-platform <postgres-pod-name> -- \
psql -U permit -d permit -c \
"UPDATE v2.v2_organization
SET is_enterprise = false,
usage_limits = jsonb_set(usage_limits, '{billing_tier}', '\"pro\"')
WHERE id = '<organization-uuid>';"
The migrations job sets every organization whose tier isn't Enterprise to Enterprise. The next installer run or upgrade changes a PRO organization back to Enterprise.
Database field reference
is_enterprise (boolean)
| Value | Tier |
|---|---|
true | Enterprise |
false | PRO or Trial, depending on usage_limits.billing_tier |
usage_limits (JSONB)
usage_limits holds the organization's limits and its billing tier. The comments in the example explain each field:
{
"mau": 5000, // Monthly Active Users limit
"tenants": 50, // Tenant limit
"billing_tier": "trial" // Billing status: "trial", "pro", or "enterprise"
}
billing_tier accepts "trial", "pro", or "enterprise". The trial countdown message in the frontend depends on billing_tier.
Rules for editing the tier fields
- Update both fields. If you change only
is_enterprise, the trial countdown message stays. - Use lowercase tier values. Write
"trial","pro", and"enterprise"in lowercase. - Back up first. A wrong
WHEREclause changes other organizations. See Create backups. - Refresh the browser. The frontend can show the old tier until you hard refresh or sign in again.
Troubleshooting
Changes not visible in the frontend
- Hard refresh the browser:
Ctrl+Shift+Ron Windows and Linux,Cmd+Shift+Ron macOS. - Clear the browser cache.
- Sign out and sign in again.
Organization not found
List all organizations to find the correct name or id:
kubectl exec -n permit-platform <postgres-pod-name> -- \
psql -U permit -d permit -c \
"SELECT id, name, key, is_enterprise FROM v2.v2_organization;"
Permission denied
A kubectl exec permission error means your Kubernetes user can't exec into pods in the namespace. Ask your cluster administrator for pods/exec access. A PostgreSQL permission error means the database user in the command lacks write access to v2.v2_organization.
Database schema reference
Table: v2.v2_organization
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
name | text | Organization name |
key | text | Organization key |
is_enterprise | boolean | Enterprise tier flag |
usage_limits | jsonb | Usage limits and billing tier |
settings | jsonb | Additional settings |
created_at | timestamp with time zone | Creation time |
updated_at | timestamp with time zone | Last update time |