Pro App Table Storage

Pro apps can keep their own records in the managed backend — orders, settings, favourites, drafts, checklists, anything that does not belong in ERP.net and is not a document. This page explains the data model, the limits, and how you work with tables.

When to use tables

Need Use
Business data that belongs to the ERP system ERP.net entities
A document, spreadsheet or reference list you upload Stored files
Records the app itself creates and updates Tables

If you ask an app to "remember my last selection", "keep a list of requests", or "save this form for later", tables are the right place.

Data model

A table is a container of rows; each row holds one record.

How you choose keys decides how fast the app is:

Lookup Speed
By row key instant
By group key, or a range inside a group fast, indexed
By name (starts with, or contains) fast, indexed
By created, changed or business date fast, indexed
By any other value inside the row slower — the whole group is scanned

What every row records automatically

Beyond what you store, each row keeps its own history:

Both dates are indexed, so questions like "everything added this week" or "the twenty most recently changed records" answer instantly, no matter how big the table is.

The business date

Many records have one date that the business actually cares about — the document date, the activity date, the due date, the effective date. That is different from when the row happened to be typed in.

Each table can switch on a single business date and give it a name. When it is on, every row can carry that date, it is indexed, and filtering or sorting by it is fast. Rows that leave it empty cost nothing.

Turn it on when creating the table in Backend → Tables (or ask the App Builder), name it after what it means, and the column appears in the row list.

Add a business date called "Document date" to the invoices table.
Show the invoices with a document date in July, newest first.
List the requests created in the last 7 days.

Use it instead of keeping that date inside the row content — a date buried in the content cannot be searched quickly.

Designing your tables

Your ERP.net data comes first

When your app runs against a connected ERP.net instance, the ERP.net schema takes precedence. The App Builder checks the ERP.net entities and your custom attributes before it proposes any table, and it stores business data — orders, partners, products, documents — where it belongs: in ERP.net. Tables are used for what ERP.net does not model, for example saved filters and layouts, drafts that are not posted yet, app-specific lists and mappings, or records the app keeps for itself. A table may point at an ERP.net record, but it never becomes a second copy of it.

If your app is standalone, with no instance connected, there is nothing to defer to — the App Builder designs the tables freely and they act as the app's own database.

The four elements above are not interchangeable — how you assign them decides how fast the app feels. When you ask for storage, the App Builder proposes a design first and asks you to confirm it.

A worked example — daily requests:

Table: requests (per instance)
Row key:   generated automatically   the row's permanent address
Group key: 2026-08                   the month the list screen shows
Name:      Acme Ltd - 3 pallets      what appears in the list
Data:      request number, customer, quantity, status, notes, delivery address

The request number lives in the data, where it can be corrected. If instead the app stored one row per ERP.net partner, the partner's id would be the natural row key — it never changes, and the app can write the row without looking it up first.

The App Builder also keeps a written schema of every table it creates — the meaning of the keys and the fields expected inside the data — so later conversations pick up exactly where the previous one left off.

Enabling table storage

Table storage is available only for Pro apps.

  1. Open the app in the App Builder.
  2. Switch to the Backend tab.
  3. Select Tables from the left menu.
  4. Turn on Tables.

Or simply ask the App Builder:

Enable tables for this app and create a table for the daily requests.

The App Builder turns the setting on itself (the app must already be Pro), creates the tables, and can fill them with reference data.

Read-only tables

Any table can be marked read-only. The running app can still read it, but only you and the App Builder can change its rows. This is useful for reference data such as price lists, statuses, or configuration.

Active and inactive rows

Every row has an Active value, switched on when the row is created.

Switching a row off keeps it — with its full history — but takes it out of circulation: lists, searches and counts in the app return active rows only. This is the right way to retire a price, a status or an old request without deleting anything. Finding the active rows stays fast no matter how many retired ones pile up.

Inactive rows are still reachable when they are asked for explicitly: the app can request them, and looking a row up directly by its row key always finds it, active or not.

In Backend → Tables each row shows an Active switch you can flip, and a Show inactive toggle above the list reveals the retired rows.

Things you can ask the App Builder:

Mark the discontinued statuses as inactive instead of deleting them.
Show me the inactive rows in the price list.
When an order is cancelled, deactivate its row instead of removing it.

Letting the app create tables

By default the app can only use tables that already exist. Turn on Allow the app to create new tables at runtime when the app genuinely needs to create containers on the fly.

Browsing tables

The Backend → Tables section shows every table of the app with its scope, read-only badge, row count and stored size. Selecting a table lists its rows — group key, row key and name — with a search box, and clicking a row opens its full content.

What you can ask the App Builder

Keep the submitted requests in a table, grouped by month.
Remember the last filter each user selected.
Create a table with the delivery statuses and mark it read-only.
Show me the rows added this month for customer Acme.

Limits

Rows are private to the app, and an app connected to one ERP.net instance never sees the rows of another — unless the table is global.