Skip to content

Build1 publisher3 min readPublished

NocoBase's 2.2.14 upgrade adds 44 columns, 42 of them in four new tables

One NocoBase user diffed a 2.1.39-to-2.2.14 upgrade on PostgreSQL 16 and found 44 new columns, only two of them on existing tables. The same test shows admin-built pages live in flowModels, so any upgrade check has to hash that table's JSON before and after.

The Engineer · Build desk

Illustration accompanying NocoBase's 2.2.14 upgrade adds 44 columns, 42 of them in four new tables

What happened

  • NocoBase published six patch releases between September 5 and 11, according to the dev.to post that went on to measure one upgrade.
  • A user on 2.1.30 asked the official NocoBase forum for an upgrade matrix covering change size, impact and whether versions can be skipped, and no staff member replied.
  • On September 20 the post's author upgraded official Docker images from 2.1.39 to 2.2.14 on PostgreSQL 16, diffing against snapshots and a fresh 2.2.14 install.
  • Four new tables hold 42 of the 44 new columns, existing tables gain two, and no table or column is dropped.
  • A page built in the admin UI before the upgrade showed the same three rows, column order and "Total 3 items" pager afterward, and its stored definition matched.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • exposure A 2.2 upgrade writes layout rows against every existing route, so snapshots and diffs of a live database will show changes no admin made, even on instances that never use layouts.
  • decision Pre-upgrade snapshots have to include flowModels. A backup-and-diff plan scoped to uiSchemas would be watching a table the admin UI never writes.
  • constraint Page-generation scripts that write uiSchemas trees produce blank pages on both 2.1 and 2.2, so any automation has to write flowModels rows and their stepParams JSON instead.

The two columns that land on existing tables are `workflows.invalid`, a boolean, and `aiConversations.scope`, a character varying [7]. The upgrade also writes rows. `uiLayouts` and `desktopRoutesUiLayouts` are new in 2.2, and after the in-place upgrade neither was empty [17]. `uiLayouts` held `admin-layout-model` for desktop and `mobile-layout-model` for mobile. `desktopRoutesUiLayouts` mapped both existing routes to `admin-layout-model` [17]. Three migrations in the `ui-layout` plugin do this. `ensure-default-admin-layout` creates the two layouts, and `backfill-admin-layout-desktop-routes` attaches every route in `desktopRoutes` that has no layout yet. `backfill-late-admin-layout-desktop-routes` then runs the same backfill again later [18].

A page built in the admin UI does not go into `uiSchemas`. It goes into `flowModels`, and its route has a different type [12]. `flowModels` has three columns, `uid`, `name` and a JSON `options`, and the whole page tree lives in that JSON [14]. The author's one-block page came to eight rows [14]. The binding to the collection sits in `stepParams`, where `resourceSettings.init` names `dataSourceKey` "main" and `collectionName` "items" [15].

`uiSchemas` is the older engine, and the UI does not write to it [13]. According to the author, inserting a Page, Grid, Grid.Row, Grid.Col, CardItem hierarchy into `uiSchemas` and pointing a `type: "page"` route at it gives a working menu entry with a blank body, on 2.1.39 and 2.2.14 alike [13]. The page exists in the sense that it has a menu entry. The author built the test page through the UI for this reason. "Writing the schema straight through the API would have been faster, and it would not have been a valid test," the author wrote [11].

The author's check is a hash per row: `select uid, md5(options::text) from "flowModels" order by uid;`, run before the upgrade and again after [16]. Row counts alone will not show whether a definition was rewritten [16]. An md5 of `options` changes when any byte of that JSON changes, so a rewritten page shows up as a new digest on the same `uid`.

The clean page result comes from a small workload. The test page had one collection of three rows, one table block and one visible column [9], running on official Docker images with PostgreSQL 16 [5]. For the result to transfer, a production instance's pages would need to live in `flowModels` the same way, and its plugins would need to leave those rows alone during migration. The forum user who asked for a matrix is on 2.1.30 [2], nine patch numbers below the tested starting point [20]. One reply in that thread came from someone who upgrades every version in order and never skips one, "for fear of problems" [3]. The test did the opposite, with one in-place jump from 2.1.39 to 2.2.14 [5].

What to watch

  • A staff reply on forum thread t/14099, or a published upgrade matrix giving change size, impact and skip-safety for each release.
  • What sets the new workflows.invalid flag, and what a true value does to an existing workflow after the upgrade.
  • A repeat of the diff starting from 2.1.30, or on an instance running custom plugins that touch flowModels.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories