Nothing wrong with Primary Keys from the 80ties!

Business Central, being a “kid” from the 80’ties, rocks classic alphanumeric primary keys. In this video, I take a look at the primary key situation, check it out:

https://youtu.be/slVfUb11_cY

In this opinion piece, Erik shares his thoughts on why the human-readable, code-based primary keys that have been part of Business Central (and its predecessors NAV/Navision) since the 1980s are actually a well-designed choice — and why replacing them with auto-incrementing integer IDs introduces real problems for users and developers alike.

What Are “Primary Keys from the 80s”?

The term comes from a comment Erik overheard in a meeting with members of the Business Central product group, where someone suggested redesigning the system to get rid of “ugly 80s primary keys.” That comment stuck with Erik, and this video is his response.

So what exactly are these primary keys? Open up the Customer card in Business Central and you’ll see a perfect example: a customer number — up to 20 characters, not limited to digits — that serves as the primary key. It’s human-readable, easy to type, and easy to communicate between people. Sometimes users put meaning into these numbers, building systems to distinguish customer numbers from vendor numbers or item numbers at a glance.

Scroll down to the posting setup area and you’ll see more examples: a General Business Posting Group called “DOMESTIC,” or customer posting groups, discount groups, and tax area codes — all using short, readable code values as their primary keys. When you open a posting setup matrix, you’re looking at a cross-reference of two such primary keys, and everything is immediately understandable.

The “Modern” Alternative: Auto-Increment IDs

Erik then shows what happens when Business Central departs from this pattern. His first example is Item Attributes (Table 7500), which uses an auto-incrementing integer as its primary key — what Erik calls a “MySQL-inspired primary key” from the early 2000s.

Looking at the source code for the Item Attribute table, you can see the design:

field(ID; Integer)
{
    AutoIncrement = true;
}

keys
{
    key(PK; ID)
    {
    }
}

The ID field is an auto-incrementing integer that serves as the primary key. When you try to create a new attribute called “Color” and one already exists with that name, you get a validation error — but that validation comes from custom code checking the Name field, not from the primary key itself.

The IDs end up being arbitrary numbers: 7, 8, 3, and so on, depending on the order of creation. This creates a real problem:

  • If you have two companies and you share items between them, unless you create the attributes in exactly the same order in both companies, they’ll get different IDs.
  • When you try to do reporting across companies, ID 7 in one company might be “Color” while ID 4 in the other company is “Color” — it’s a total mess.
  • If this had been designed with a code-based primary key (an “80s primary key”), the only difference on the page would be an extra column — and it would look and behave like hundreds of other tables in the system.

Another Example: Job Queue Entries

Erik’s second example is Job Queue Entries, which use a GUID as their primary key. He demonstrates the problem by creating two identical-looking job queue entries — both set to run Report 110 (Customer Labels). From the user interface, they look exactly the same. There’s no way for one administrator to tell another “this specific job failed” because the visible information is identical.

Behind the scenes, each entry has a unique GUID, but GUIDs are not something a user can easily read, communicate, or type into an email. The on-insert code generates a GUID automatically if one isn’t present, but this key is essentially invisible to users.

This would have been far better with a human-readable primary key — a short code that users could reference in emails, error logs, and conversations.

Adding Keys to Standard Tables

On a related practical note, Erik’s sample project demonstrates how you can extend standard tables with additional keys using AL extensions. Here’s an example of adding a secondary key to the Sales Invoice Header:

tableextension 50138 "My Sales Invoice" extends "Sales Invoice Header"
{
    fields
    {
        field(50138; MyField; Code[20])
        {
            Caption = 'My Field';
        }
    }
    keys
    {
        key(ExtDocKey; "External Document No.")
        {
        }
    }
}

This table extension adds a new field and a secondary key on the “External Document No.” field. It’s a straightforward example of how the AL extension model lets you add indexing to standard tables when you need to optimize lookups on fields that aren’t part of the original key structure.

Conclusion

Erik’s core argument is simple: the human-readable, code-based primary keys that NAV/Navision/Business Central have used since the 1980s offer a very high degree of usability for the user base the software is designed for. They’re easy to read, easy to communicate, easy to type, and they work consistently across companies and environments. While other software does things differently with auto-incrementing integers or GUIDs, the places where Business Central has adopted those “modern” patterns — like Item Attributes and Job Queue Entries — actually demonstrate why the original approach was better. The “ugly” primary keys from the 80s might not look fashionable, but they’re highly effective, and there are far more beneficial areas to focus improvement efforts on than replacing them.