Email this post as a PDFDevelopment · 8 October 2026 · 3 min read

Retention policies for your own tables: stop your extension filling the database

Every extension that logs something, stages something or archives something grows a table forever unless someone deletes from it. Business Central has a standard retention policy engine; your tables should register with it rather than ship a "delete old entries" job of their own. How to register a table, what the policy can do, and which tables in a typical extension need one.

Contents
  1. Register your table
  2. What it does
  3. Ship a default
  4. Which tables in a typical extension
  5. Why not your own clean-up job

Integration logs, staging tables, imported files, audit records, telemetry copies: every extension has at least one table that only grows. Left alone it becomes the biggest table in the database, slows every backup and copy, and costs storage. Business Central's Retention Policy module exists so the administrator can set "keep 90 days" on any registered table and a job queue entry does the rest.

Register your table

In your install codeunit (and the upgrade codeunit for existing installs):

local procedure AddRetentionPolicyAllowedTables()
var
    RetenPolAllowedTables: Codeunit "Reten. Pol. Allowed Tables";
    IntegrationLog: Record "CON Integration Log";
begin
    RetenPolAllowedTables.AddAllowedTable(Database::"CON Integration Log", IntegrationLog.FieldNo(SystemCreatedAt));
end;

The second argument is the date or datetime field the policy filters on; SystemCreatedAt works for anything that does not have a business date of its own. Once registered, the table appears in the Retention Policies page and the administrator can create a policy: a retention period (Microsoft ships 1 week to 1 year plus "never delete"; they can add their own), optional filters (keep errors longer than successes, by status), and whether to apply to all records or only matching ones.

What it does

The job queue entry "Retention Policy JQ" runs (daily by default), finds records older than the period per policy line, and deletes them in batches with a limit per run, so a huge backlog is cleared over several nights rather than locking the table for an hour. It logs what it deleted. Deletions are plain Delete without triggers by default; if your table's OnDelete matters (cascading to lines), register with AddAllowedTable(TableId, DateFieldNo, NumberOfDays, RunTriggers) or subscribe to the OnApplyRetentionPolicyRecordLimitExceeded-family events to handle it.

Ship a default

Registering is not enough; set a sensible default policy in the install codeunit (RetentionPolicySetup with a period) so that a customer who never opens the page still does not fill the database. They can change it.

Which tables in a typical extension

  • Integration and API call logs: 30 to 90 days, errors longer.
  • Staging / import tables: 7 to 30 days after processing.
  • Archived or posted copies the business does not need to keep: by its own policy, often years.
  • Notification or email queues: days.
  • Anything with a Blob or Media field: shorter than you think.

Not: ledger entries, posted documents or anything the audit trail needs. Microsoft's own policies cover change log, job queue log, sent emails and the like; look at those before writing your own.

Why not your own clean-up job

Because the administrator then has two places to configure retention, your job has no batching, no log and no filters, and the next developer does not know it exists. The standard engine is already on the job queue, already in the audit, and already understood by whoever runs the system. Registering a table is five lines; a clean-up codeunit is fifty and a support ticket.

Email this post as a PDF
A branded PDF of this post, sent to your inbox to keep, print or share. Copy in colleagues if you like.
We only use these addresses to send this PDF. Nobody is added to a mailing list. Mike at Business Boxed receives a copy. See our privacy notice.
Email this post
Talk to us
Want this done in your Business Central?
Book a 30 minute callGet the monthly newsletter

Related posts