Press ESC to exit fullscreen
📖 Lesson ⏱️ 75 minutes

Object Types

Define the nouns of your business: customers, flights, sensors, orders. Properties, primary keys, titles

What is an object type?

An object type is the definition of a kind of entity — the class. The instances of that class are objects.

If you come from a programming background, the analogy is exact:

class Customer {           // ← object type (definition)
  customerId: string;      // ← property
  firstName: string;
  region: Region;
}

const alice = new Customer(...);  // ← object (instance)
const bob   = new Customer(...);  // ← object (instance)

If you come from relational thinking: an object type is roughly a table; an object is a row. The difference is that an object type carries a lot more than a table schema — display names, descriptions, primary key, title key, link bindings, and governance.

The minimum viable definition

Every object type needs at least:

  1. An API name — stable, immutable, used in code (Customer, Shipment).
  2. A display name — what users see ("Customer", "Shipment").
  3. A description — what this entity means in the business.
  4. A primary key — the property that uniquely identifies an instance.
  5. A title key — the property used to label an instance in UIs.
  6. At least one property.

Example (we use a YAML-ish pseudo-schema throughout this course; the exact syntax varies by platform):

objectType: Customer
displayName: Customer
description: >
  A business or individual that has signed a service agreement with us.
  Excludes prospects, trial accounts, and internal test users.
apiName: customer
primaryKey: customerId
titleKey: companyName
properties:
  - name: customerId
    type: string
    description: Stable identifier from the operational DB
  - name: companyName
    type: string
  - name: region
    type: enum<Region>
  - name: signedAt
    type: timestamp

That description matters more than people expect. A clear, scoped description prevents the “what counts as a customer?” debate every six months.

Choosing a primary key

The primary key is the decision that locks in the longevity of your object type. Get it right.

Good primary keys:

  • Are stable — they never change for the lifetime of the entity.
  • Are business-meaningfulshipment_id = "SHP-2026-04-13-00871", not 42.
  • Are traceable — you can find the same ID in the source system.

Avoid:

  • Autoincrement integers from a single environment. They collide across dev/staging/prod.
  • Composite keys when you can mint a single ID. Composites make link types painful.
  • Mutable natural keys like email addresses — emails change.
  • UUIDs with no business meaning — they work, but make debugging miserable. If you must use them, expose a human-readable secondary identifier too.

If a source system gives you a stable ID, reuse it. If not, mint one with a clear, structured format and put the source’s ID as a regular property.

Title key vs primary key

The title key is what users see in dropdowns, breadcrumbs, link previews — the human label.

  • Primary key: customerId = "cust_1f7a3" — for machines.
  • Title key: companyName = "Globex GmbH" — for humans.

The title key does not have to be unique. Two customers can both be named “Acme Corp” — the primary key still distinguishes them.

Intrinsic vs derived properties

A property is intrinsic if it comes directly from the datasource:

  • Customer.companyName — comes from the operational DB.
  • Customer.signedAt — recorded at signup.

A property is derived if it is computed:

  • Customer.totalLifetimeValue — sum of all order amounts.
  • Customer.isActivelastOrderAt > now() - 90d.

Both can live on an object type, but they should be tagged differently. Derived properties:

  • Are computed by functions (covered in a later lesson).
  • May be cached but should always be reproducible.
  • Should not be writable by actions (that would invert the dataflow).

Mixing them without a clear convention causes confusion: “why did totalLifetimeValue not change after I edited the order?” Because it is derived — you cannot edit it; you edit the source.

What goes on an object type — and what does not

A common anti-pattern is the junk drawer object type: a User with 80 properties, half of which apply to 2% of users.

Rules of thumb:

Belongs on the object type:

  • Properties that are always present for an instance (with a sensible nullability rule).
  • Properties that describe the entity itself, not its history.

Probably belongs elsewhere:

  • Time series (every login event) → a separate object type (LoginEvent) with a link to User.
  • Variant-specific properties that only apply for some instances → consider splitting into multiple object types or using an interface (covered later).
  • Free-form blobs (notes, conversations) → either link to a Note object type or store as attachment properties.

Cardinality rule of thumb

A useful test: if most instances of this object type have most of these properties populated, the model is healthy. If half the properties are NULL for the typical row, you have a modeling problem hiding in nullability.

A complete example — Shipment

Putting it together for a logistics company:

objectType: Shipment
displayName: Shipment
description: >
  A package or pallet in transit from an origin to a destination,
  associated with exactly one Order and (optionally) one Driver
  at a time.

apiName: shipment
primaryKey: shipmentId        # SHP-YYYY-MM-DD-NNNNN
titleKey: shipmentId          # IDs *are* what users look for here

properties:
  - name: shipmentId
    type: string
    description: Stable identifier from dispatch system
  - name: status
    type: enum<ShipmentStatus>   # created | in_transit | out_for_delivery | delivered | exception
  - name: weightKg
    type: double
    description: Gross weight in kilograms; null if not yet weighed
    nullable: true
  - name: originHubId
    type: string
  - name: destinationHubId
    type: string
  - name: createdAt
    type: timestamp
  - name: deliveredAt
    type: timestamp
    nullable: true
  - name: dimensions
    type: struct<length: double, width: double, height: double, unit: enum<LengthUnit>>
    nullable: true

# We will add link types and actions in later lessons

A few things to notice:

  • The description constrains scope. “A Shipment” is not just any row in shipments.csv — it is a specific concept.
  • Properties have descriptions where the name alone is not enough.
  • weightKg is explicitly nullable because not every shipment is weighed at creation. We name it weightKg, not weight, so units are part of the type.
  • dimensions uses a struct rather than three separate properties — they belong together.

Naming conventions that age well

  • Object types in PascalCase. Customer, OrderLine, Shipment.
  • Properties in camelCase. firstName, weightKg, deliveredAt.
  • Booleans read true. isActive not active; hasInsurance not insurance.
  • Units in the name when the type is ambiguous: weightKg, latencyMs, priceUsd.
  • At for timestamps. createdAt, deliveredAt. Date is too vague.
  • Id for foreign references to other objects. customerId not customer.

These look minor on day one. By month six, with thirty object types and four hundred properties, they save you constantly.

Anti-patterns to avoid

  • The God object type. Entity with type field, holding customers, suppliers, partners, and prospects in one bag. Split it.
  • The reporting object type. MonthlyRevenueByRegion — that is a query, not an object type. Use functions.
  • The mirror-of-the-table object type. Copying your raw users table verbatim and calling it done. The ontology should interpret the data, not just rename columns.
  • Property soup. Every column from every source system, glued together with NULLs. Curate.

Key takeaways

  • An object type is the typed definition of an entity in your business.
  • It needs a stable primary key, a human-friendly title key, and a clear description.
  • Distinguish intrinsic (source-of-truth) and derived (computed) properties.
  • Naming and scoping discipline early saves enormous pain later.

What’s next

Object types are made of property types. Next lesson: the typing system — strings, integers, geo-points, structs, arrays, attachments — and what good typing buys you.


The nouns are named. Now we type them. 🏷️