electric-schema-shapes

Design Postgres schema and Electric shape definitions together for a new feature. Covers single-table shape constraint, cross-table joins using multiple shapes, WHERE clause design for tenant isolation, column selection for bandwidth optimization, replica mode choice (default vs full for old_value), enum casting in WHERE clauses, and txid handshake setup with pg_current_xact_id() for optimistic writes. Load when designing database tables for use with Electric shapes.

25 stars

Best use case

electric-schema-shapes is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Design Postgres schema and Electric shape definitions together for a new feature. Covers single-table shape constraint, cross-table joins using multiple shapes, WHERE clause design for tenant isolation, column selection for bandwidth optimization, replica mode choice (default vs full for old_value), enum casting in WHERE clauses, and txid handshake setup with pg_current_xact_id() for optimistic writes. Load when designing database tables for use with Electric shapes.

Teams using electric-schema-shapes should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/electric-schema-shapes/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/electric-sql/electric/electric-schema-shapes/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/electric-schema-shapes/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How electric-schema-shapes Compares

Feature / Agentelectric-schema-shapesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Design Postgres schema and Electric shape definitions together for a new feature. Covers single-table shape constraint, cross-table joins using multiple shapes, WHERE clause design for tenant isolation, column selection for bandwidth optimization, replica mode choice (default vs full for old_value), enum casting in WHERE clauses, and txid handshake setup with pg_current_xact_id() for optimistic writes. Load when designing database tables for use with Electric shapes.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

This skill builds on electric-shapes. Read it first for ShapeStream configuration.

# Electric — Schema and Shapes

## Setup

Design tables knowing each shape syncs one table. For cross-table data, use multiple shapes with client-side joins.

```sql
-- Schema designed for Electric shapes
CREATE TABLE todos (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL,
  text TEXT NOT NULL,
  completed BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT now()
);

ALTER TABLE todos REPLICA IDENTITY FULL;
```

```ts
import { ShapeStream } from '@electric-sql/client'

const todoStream = new ShapeStream({
  url: '/api/todos', // Proxy sets: table=todos, where=org_id=$1
})
```

## Core Patterns

### Cross-table data with multiple shapes

```ts
// Each shape syncs one table — join client-side
const todoStream = new ShapeStream({ url: '/api/todos' })
const userStream = new ShapeStream({ url: '/api/users' })

// With TanStack DB, use .join() in live queries:
// q.from({ todo: todoCollection })
//   .join({ user: userCollection }, ({ todo, user }) => eq(todo.userId, user.id))
```

### Choose replica mode

```ts
// Default: only changed columns sent on update
const stream = new ShapeStream({ url: '/api/todos' })

// Full: all columns + old_value on updates (more bandwidth, needed for diffs)
const stream = new ShapeStream({
  url: '/api/todos',
  params: { replica: 'full' },
})
```

### Backend txid handshake for optimistic writes

Call `pg_current_xact_id()::xid::text` inside the same transaction as your mutation. If you query it outside the transaction, you get a different txid and the client will never reconcile.

```ts
// API endpoint — txid MUST be in the same transaction as the INSERT
app.post('/api/todos', async (req, res) => {
  const client = await pool.connect()
  try {
    await client.query('BEGIN')
    const result = await client.query(
      'INSERT INTO todos (id, text, org_id) VALUES ($1, $2, $3) RETURNING id',
      [crypto.randomUUID(), req.body.text, req.body.orgId]
    )
    const txResult = await client.query(
      'SELECT pg_current_xact_id()::xid::text AS txid'
    )
    await client.query('COMMIT')
    // txid accepts number | bigint | `${bigint}`
    res.json({ id: result.rows[0].id, txid: parseInt(txResult.rows[0].txid) })
  } finally {
    client.release()
  }
})
```

```ts
// Client awaits txid before dropping optimistic state
await todoCollection.utils.awaitTxId(txid)
```

## Common Mistakes

### HIGH Designing shapes that span multiple tables

Wrong:

```ts
const stream = new ShapeStream({
  url: '/api/data',
  params: {
    table: 'todos JOIN users ON todos.user_id = users.id',
  },
})
```

Correct:

```ts
const todoStream = new ShapeStream({ url: '/api/todos' })
const userStream = new ShapeStream({ url: '/api/users' })
```

Shapes are single-table only. Cross-table data requires multiple shapes joined client-side via TanStack DB live queries.

Source: `AGENTS.md:104-105`

### MEDIUM Using enum columns without casting to text in WHERE

Wrong:

```ts
// Proxy route
originUrl.searchParams.set('where', "status IN ('active', 'done')")
```

Correct:

```ts
originUrl.searchParams.set('where', "status::text IN ('active', 'done')")
```

Enum types in WHERE clauses require explicit `::text` cast. Without it, the query may fail or return unexpected results.

Source: `packages/sync-service/lib/electric/replication/eval/env/known_functions.ex`

### HIGH Not setting up txid handshake for optimistic writes

Wrong:

```ts
// Backend: just INSERT, return id
app.post('/api/todos', async (req, res) => {
  const result = await db.query(
    'INSERT INTO todos (text) VALUES ($1) RETURNING id',
    [req.body.text]
  )
  res.json({ id: result.rows[0].id })
})
```

Correct:

```ts
// Backend: INSERT and return txid in same transaction
app.post('/api/todos', async (req, res) => {
  const client = await pool.connect()
  try {
    await client.query('BEGIN')
    const result = await client.query(
      'INSERT INTO todos (text) VALUES ($1) RETURNING id',
      [req.body.text]
    )
    const txResult = await client.query(
      'SELECT pg_current_xact_id()::xid::text AS txid'
    )
    await client.query('COMMIT')
    res.json({ id: result.rows[0].id, txid: parseInt(txResult.rows[0].txid) })
  } finally {
    client.release()
  }
})
```

Without txid, the UI flickers when optimistic state is dropped before the synced version arrives from Electric. The client uses `awaitTxId(txid)` to hold optimistic state until the real data syncs.

Source: `AGENTS.md:116-119`

See also: electric-shapes/SKILL.md — Shapes are immutable; dynamic filters require new ShapeStream instances.
See also: electric-orm/SKILL.md — Schema design affects both shapes (read) and ORM queries (write).

## Version

Targets @electric-sql/client v1.5.10.

Related Skills

validating-api-schemas

25
from ComeOnOliver/skillshub

Validate API schemas against OpenAPI, JSON Schema, and GraphQL specifications. Use when validating API schemas and contracts. Trigger with phrases like "validate API schema", "check OpenAPI spec", or "verify schema".

schema-validator

25
from ComeOnOliver/skillshub

Schema Validator - Auto-activating skill for Data Pipelines. Triggers on: schema validator, schema validator Part of the Data Pipelines skill category.

response-schema-generator

25
from ComeOnOliver/skillshub

Response Schema Generator - Auto-activating skill for API Development. Triggers on: response schema generator, response schema generator Part of the API Development skill category.

prisma-schema-helper

25
from ComeOnOliver/skillshub

Prisma Schema Helper - Auto-activating skill for Backend Development. Triggers on: prisma schema helper, prisma schema helper Part of the Backend Development skill category.

graphql-schema-generator

25
from ComeOnOliver/skillshub

Graphql Schema Generator - Auto-activating skill for API Development. Triggers on: graphql schema generator, graphql schema generator Part of the API Development skill category.

designing-database-schemas

25
from ComeOnOliver/skillshub

Process use when you need to work with database schema design. This skill provides schema design and migrations with comprehensive guidance and automation. Trigger with phrases like "design schema", "create migration", or "model database".

database-schema-visualizer

25
from ComeOnOliver/skillshub

Database Schema Visualizer - Auto-activating skill for Visual Content. Triggers on: database schema visualizer, database schema visualizer Part of the Visual Content skill category.

comparing-database-schemas

25
from ComeOnOliver/skillshub

This skill leverages the database-diff-tool plugin to compare database schemas, generate migration scripts, and provide rollback procedures. It is triggered when the user requests database schema comparisons, migration script generation, or database synchronization. Use this skill when asked to identify differences between database schemas (PostgreSQL or MySQL), create safe migration scripts with transaction safety, validate changes before deployment, or generate rollback procedures. The skill is activated by requests involving terms like "database diff", "schema comparison", "generate migration script", "database synchronization", or `/db-diff`.

electric-yjs

25
from ComeOnOliver/skillshub

Set up ElectricProvider for real-time collaborative editing with Yjs via Electric shapes. Covers ElectricProvider configuration, document updates shape with BYTEA parser (parseToDecoder), awareness shape at offset='now', LocalStorageResumeStateProvider for reconnection with stableStateVector diff, debounceMs for batching writes, sendUrl PUT endpoint, required Postgres schema (ydoc_update and ydoc_awareness tables), CORS header exposure, and sendErrorRetryHandler. Load when implementing collaborative editing with Yjs and Electric.

electric-shapes

25
from ComeOnOliver/skillshub

Configure ShapeStream and Shape to sync a Postgres table to the client. Covers ShapeStreamOptions (url, table, where, columns, replica, offset, handle), custom type parsers (timestamptz, jsonb, int8), column mappers (snakeCamelMapper, createColumnMapper), onError retry semantics, backoff options, log modes (full, changes_only), requestSnapshot, fetchSnapshot, subscribe/unsubscribe, and Shape materialized view. Load when setting up sync, configuring shapes, parsing types, or handling sync errors.

electric-proxy-auth

25
from ComeOnOliver/skillshub

Set up a server-side proxy to forward Electric shape requests securely. Covers ELECTRIC_PROTOCOL_QUERY_PARAMS forwarding, server-side shape definition (table, where, params), content-encoding/content-length header cleanup, CORS configuration for electric-offset/electric-handle/ electric-schema/electric-cursor headers, auth token injection, ELECTRIC_SECRET/SOURCE_SECRET server-side only, tenant isolation via WHERE positional params, onError 401 token refresh, and subset security (AND semantics). Load when creating proxy routes, adding auth, or configuring CORS for Electric.

electric-postgres-security

25
from ComeOnOliver/skillshub

Pre-deploy security checklist for Postgres with Electric. Checks REPLICATION role, SELECT grants, CREATE on database, table ownership, REPLICA IDENTITY FULL on all synced tables, publication management (auto vs manual with ELECTRIC_MANUAL_TABLE_PUBLISHING), connection pooler exclusion for DATABASE_URL (use direct connection), and ELECTRIC_POOLED_DATABASE_URL for pooled queries. Load before deploying Electric to production or when diagnosing Postgres permission errors.