Seed and Read Relationship Data

This guide assumes the model already contains a relationship. Define one with Relationships and Extensions, then promote the schema before seeding links.

const projects = collection('projects', {
  fields: {
    title: bd.text().required(),
    client: bd
      .relation()
      .references('clients')
      .onDelete('RESTRICT')
      .required(),
  },
})

A relation is not stored inside the row's ordinary values. Links are separate records keyed by the source row, relation field, and target row.

This is intentionally wrong:

{
  "values": {
    "title": "Storefront redesign",
    "client": "client-row-uid"
  }
}

Put the link in relations:

[
  {
    "object": "project-object-uid",
    "universalIdentifier": "project-row-uid",
    "values": {
      "title": "Storefront redesign"
    },
    "relations": {
      "client": "client-row-uid",
      "tags": [
        "priority-tag-row-uid",
        "design-tag-row-uid"
      ]
    }
  }
]

The keys in relations are relation field names. Each target is a row universalIdentifier, not the target collection identity.

Preview and sync

npx bd sync-records --dry-run
npx bd sync-records

The CLI runs in two passes:

  1. converge all record values,
  2. resolve and converge relation links.

Because target rows exist before the second pass, seed-file ordering does not have to follow relationship ordering.

Per-field convergence

For each relation field present in the seed:

  • missing links are added,
  • existing links omitted from the declared list are removed,
  • [] explicitly clears a multi-link field,
  • a relation field absent from the seed is left unchanged.

This means dashboard-managed links survive unless the seed claims ownership of that relation field.

Failure behavior

A misspelled relation field or an unknown target row fails that row's relation work with a focused error. The record itself can still save, the remaining batch continues, and the CLI exits non-zero so CI notices.

Record reads return relation fields separately:

{
  "id": "project-database-id",
  "universalIdentifier": "project-row-uid",
  "fields": {
    "title": "Storefront redesign"
  },
  "relations": {
    "client": [
      {
        "recordId": "client-database-id",
        "object": "client-object-uid"
      }
    ],
    "tags": []
  }
}

Fetch a target record separately when its fields are needed.

Limits

  • Relation keys inside values are ignored as ordinary values.
  • Seed targets require a row universalIdentifier.
  • MORPH_RELATION is not supported by this workflow.
  • Standard BusinessDash objects use their dedicated APIs and business rules.