Each pattern shows the definition (Studio or code) and the client code.

Per-user data (notes, settings, carts)

Definition: an owner_id column, owner_field: "owner_id", and the owner quick set on the Access tab. App: from("notes").create({ text }) and from("notes"). Nothing else to write.

Team data

Definition: an org column on every table, and a rule comparing it with the caller’s organization.
App: set org: session.org on create; use switchOrg to change teams. See Organizations.

Soft delete

Keep deleted records recoverable. Definition: a nullable deleted_at datetime column. Make the list and get rules hide deleted rows: All of (Record owner; $record.deleted_at is empty). Add a partial index where deleted_at is null. App:
Remove the delete operation so nobody hard-deletes by accident.

Audit trail

Record who changed what, without trusting the client. Definition: an audit_log table whose rules are service for everything. Add a subscription from orders.updated to a flow that writes a row to audit_log using the event’s actor and payload. App: nothing. Reading history happens in a route or the table editor.

Counters and totals

Don’t increment a counter from the client: two people race. Options:
  • Compute totals on read: count() for what the person may see.
  • Keep a cached total updated by a flow on x.created / x.deleted.
  • For exactness (stock), update inside a route that does it in one database statement.

Tags (many-to-many)

A post_tags join table with two belongs_to relations and a unique composite index. See Relations.

Orderable lists (drag to reorder)

Keep a numeric position column. On drop, compute the new position between neighbours (the average of the two), so one update changes one row:
Re-number occasionally if gaps get tiny.

Public and private fields on one table

Some columns are for everyone (name), some for the owner (email). Options:
  1. Mark private columns write only if they should never be read back.
  2. Split into two tables: profiles (public) and profile_private (owner-only).
  3. Use a route that returns only the fields the public should see, and let the owner read the table directly.
Rule of thumb: access rules decide rows; for columns, split the table.

Settings and feature flags

A single-row-per-user settings table with a JSON column and the owner rules. Update with the data-style merge in the client:

Seed and fixtures

Use import with upsert and a stable key so seeding is repeatable.

Access rules recipes

More rules.

Troubleshooting

When it misbehaves.