← Back to all posts
6 min readCentrali Team

Coming Soon: Enhanced Record Relationships

We're building first-class record relationships with referential integrity, cascade behaviors, and automatic expansion. Here's a preview of what's coming.

RoadmapFeatureAnnouncement

When you're building an application, data rarely exists in isolation. Orders belong to customers. Posts have authors. Tasks are assigned to users. These relationships are fundamental to how applications work.

Today, we're sharing a preview of a major enhancement coming to Centrali: first-class record relationships with validation, cascade behaviors, and automatic expansion.

The Challenge Today

Currently, when you need to link records across structures, you store reference IDs manually:

json
{ "name": "orders", "properties": [ { "name": "customerId", "type": "string" }, { "name": "productIds", "type": "array", "items": { "type": "string" } } ] }

This works, but has limitations:

  • No validation — Nothing prevents storing an ID that doesn't exist
  • Orphaned references — Delete a customer, and all orders pointing to them become broken
  • Manual population — You need Smart Queries to fetch related data
  • No cascade behavior — Deleting related records requires manual cleanup

What We're Building

A native reference property type that solves these problems while maintaining the flexibility you expect from Centrali.

Reference Property Type

Define relationships directly in your structure schema:

json
{ "name": "orders", "properties": [ { "name": "customer", "type": "reference", "target": "customers", "displayField": "name", "required": true, "onDelete": "restrict" }, { "name": "lineItems", "type": "reference", "target": "products", "isArray": true, "onDelete": "set_null" } ] }

Validated References

When you create or update a record, Centrali will verify that referenced records actually exist:

bash
# This fails with a clear error if the customer doesn't exist POST /structures/orders/records { "customer": "cust-invalid-123", "total": 99.99 }
json
{ "error": "Reference validation failed", "details": [ { "field": "customer", "message": "Referenced record 'cust-invalid-123' not found in 'customers'" } ] }

No more orphaned references. No more silent data corruption.

Cascade Behaviors

Control what happens when a referenced record is deleted:

  • restrict — Prevent deletion if other records reference this one
  • cascade — Automatically delete all records that reference this one
  • set_null — Set the reference field to null in referencing records

Example: Restrict deletion

bash
# Attempting to delete a customer with orders DELETE /structures/customers/records/cust-123
json
{ "error": "Cannot delete record", "message": "Record is referenced by 5 records in 'orders'", "referencedBy": [ { "structure": "orders", "count": 5 } ] }

This protects your data integrity automatically.

Automatic Expansion

Fetch related data inline without writing Smart Queries:

bash
GET /structures/orders/records?expand=customer
json
{ "records": [ { "id": "order-123", "total": 99.99, "customer": "cust-456", "_expanded": { "customer": { "id": "cust-456", "name": "Acme Corp", "email": "billing@acme.com" } } } ] }

Nested expansion will also be supported:

bash
GET /structures/orders/records?expand=customer,lineItems.category

Array References

Link to multiple records for many-to-many relationships:

json
{ "name": "tags", "type": "reference", "target": "tags", "isArray": true, "onDelete": "set_null" }
json
{ "id": "post-123", "title": "My Blog Post", "tags": ["tag-1", "tag-2", "tag-3"] }

Use Cases

E-commerce

customers ←── orders (onDelete: restrict)
                │
                └──→ products (lineItems, isArray, onDelete: set_null)
  • Can't delete a customer with pending orders
  • Order line items reference products directly
  • If a product is deleted, line items become null (order preserved)

Content Management

authors ←── posts (onDelete: restrict)
              │
              └──→ categories (isArray, onDelete: set_null)
  • Authors can't be deleted while they have posts
  • Posts can have multiple categories
  • If a category is deleted, posts keep their other categories

Project Management

projects ←── tasks (onDelete: cascade)
               │
               └──→ users (assignee, onDelete: set_null)
  • Delete a project, all its tasks are deleted
  • Delete a user, tasks become unassigned (not deleted)

What This Means for You

Backward Compatible

Your existing data continues to work unchanged. The new reference type is additive:

  • Existing string fields storing IDs remain functional
  • Smart Queries continue to work for complex joins
  • Migrate to reference type when you're ready

Complements Smart Queries

This doesn't replace Smart Queries—it complements them. Use references for:

  • Simple one-to-one and one-to-many relationships
  • Data integrity enforcement
  • Convenient auto-expansion

Continue using Smart Queries for:

  • Complex multi-join queries
  • Aggregations across structures
  • Advanced filtering on joined data

Timeline

We're targeting Q1 2026 for this feature. The rollout will be phased:

  1. Phase 1: Reference property type with validation
  2. Phase 2: ?expand= query parameter for auto-population
  3. Phase 3: Cascade behaviors (restrict, cascade, set_null)
  4. Phase 4: Console UI support for defining relationships visually

We Want Your Feedback

Before we finalize the design, we'd love to hear from you:

  • What cascade behaviors matter most for your use case?
  • What relationship patterns do you need that we haven't covered?
  • Any edge cases we should consider?

Email us at feedback@centrali.io — we read every message.


This is part of our commitment to making Centrali the most developer-friendly backend platform. We're building the features you need to ship faster and maintain cleaner data.

Stay tuned for updates as we progress toward release.

Building something with Centrali and want to share feedback about this feature?

Email feedback@centrali.io