agentsclimarketplace

Powersync no foreign keys on sync backend

Skill kjuhwa/skills-hub/skills/powersync/powersync-no-foreign-keys-on-sync-backend

Skip composite foreign-key constraints on a PowerSync-style backend schema and use plain text columns for cross-table references, so partial syncs don't fail and encrypted columns don't block writes.From its SKILL.md

Install
npx -y skills add kjuhwa/skills-hub --skill powersync-no-foreign-keys-on-sync-backend

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

2.3 KB, 363 tokens by cl100k_base, as published. Nobody here has run it

When to use

You are modelling PowerSync-synced Postgres tables where some parent tables have composite primary keys like (id, user_id). The natural instinct is to add a matching composite foreign key from children. Don't.

Steps

  1. Declare the child column as a plain text column: modeId: text('mode_id'). No .references(), no foreignKey().
  2. Enforce relationships on the frontend — SQLite queries already JOIN there, and that's where business logic lives in a PowerSync app.
  3. Skip indexes on the foreign-key column. Only user_id gets an index on the backend.
  4. For default-data tables that ship with predefined IDs, expect children to temporarily point at a default parent ID that isn't yet synced on a brand-new device; the reconcile-defaults step will populate it.
  5. Validate referential integrity at the application layer (DAL or service), not the database.

Counter / Caveats

  • Confidence is medium because this inverts the default relational-DB advice; teams coming from a traditional stack often push back. Document the decision prominently in AGENTS.md or a schema comment.
  • You lose cascade-delete at the database level. If you rely on ON DELETE CASCADE, you must replicate it in the DAL or accept orphaned rows (which PowerSync tolerates by design during partial syncs).
  • If the backend gains non-sync query endpoints (admin, analytics) in the future, add FKs per-endpoint in a separate schema rather than the shared PowerSync schema.

Evidence

  • docs/composite-primary-keys-and-default-data.md:56-99
  • Example callouts: chatThreadsTable.modeId references modesTable without foreignKey()

What ships with it: 1 file

1.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,758. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.