From a4db795d9ecaf982da4ccc4faa30205808e32e99 Mon Sep 17 00:00:00 2001 From: Yash Kumar Saini Date: Mon, 24 Aug 2026 15:03:02 +0530 Subject: [PATCH 1/6] perf(db): index corsair_entities and corsair_accounts on their query paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documented sync-layer schema creates corsair_entities and corsair_accounts with no secondary indexes, yet every ORM read filters corsair_entities on (account_id, entity_type[, entity_id]) and resolves the account by (tenant_id, integration_id) before every entity op. With no matching index these are full table scans whose cost grows with the total row count across all tenants and plugins — on the very table the sync layer writes to on every webhook event. Add plain (non-unique) covering indexes to every hand-authored schema (docs + demos). A non-unique index delivers the full lookup speedup without changing any runtime failure mode. Enforcing UNIQUE on (account_id, entity_type, entity_id) is deferred to the follow-up that makes upsertByEntityId atomic (ON CONFLICT DO UPDATE): only paired with conflict handling does the constraint avoid turning a concurrent first-insert race into a failed operation, and it avoids a migration hazard on existing databases that already hold duplicate rows. Benchmark (sqlite, documented schema, findByEntityId pattern): 900k rows 61ms -> 9us per lookup; EXPLAIN QUERY PLAN goes from SCAN corsair_entities to SEARCH USING INDEX. --- demo/mcp/db.ts | 4 ++++ demo/testing/migration.sql | 6 ++++++ docs/concepts/database.mdx | 12 ++++++++++++ docs/getting-started/quick-start.mdx | 6 ++++++ docs/guides/dashboard.mdx | 6 ++++++ 5 files changed, 34 insertions(+) diff --git a/demo/mcp/db.ts b/demo/mcp/db.ts index 8d5b1372f..8d776af49 100644 --- a/demo/mcp/db.ts +++ b/demo/mcp/db.ts @@ -22,6 +22,10 @@ sqlite.exec(` dek TEXT NULL ); + -- Account lookup runs before every entity op; index its access pattern. + CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); + CREATE TABLE IF NOT EXISTS corsair_entities ( id TEXT PRIMARY KEY, created_at TEXT NOT NULL, diff --git a/demo/testing/migration.sql b/demo/testing/migration.sql index e4aebd574..b66e20299 100644 --- a/demo/testing/migration.sql +++ b/demo/testing/migration.sql @@ -41,6 +41,12 @@ CREATE TABLE IF NOT EXISTS corsair_events ( FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); +-- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). +CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); +CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx + ON corsair_entities (account_id, entity_type, entity_id); + CREATE TABLE IF NOT EXISTS corsair_permissions ( id TEXT PRIMARY KEY, created_at INTEGER NOT NULL, diff --git a/docs/concepts/database.mdx b/docs/concepts/database.mdx index 8b5c2db65..635c69096 100644 --- a/docs/concepts/database.mdx +++ b/docs/concepts/database.mdx @@ -133,6 +133,12 @@ CREATE TABLE IF NOT EXISTS corsair_events ( status TEXT, FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); + +-- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). +CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); +CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx + ON corsair_entities (account_id, entity_type, entity_id); ``` @@ -206,6 +212,12 @@ CREATE TABLE IF NOT EXISTS corsair_events ( payload JSONB NOT NULL DEFAULT '{}', status TEXT ); + +-- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). +CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); +CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx + ON corsair_entities (account_id, entity_type, entity_id); ``` diff --git a/docs/getting-started/quick-start.mdx b/docs/getting-started/quick-start.mdx index 6d84df192..40c50f2c0 100644 --- a/docs/getting-started/quick-start.mdx +++ b/docs/getting-started/quick-start.mdx @@ -127,6 +127,12 @@ CREATE TABLE IF NOT EXISTS corsair_events ( status TEXT, FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); + +-- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). +CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); +CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx + ON corsair_entities (account_id, entity_type, entity_id); ``` diff --git a/docs/guides/dashboard.mdx b/docs/guides/dashboard.mdx index 4554108db..b7cae9607 100644 --- a/docs/guides/dashboard.mdx +++ b/docs/guides/dashboard.mdx @@ -176,6 +176,12 @@ CREATE TABLE IF NOT EXISTS corsair_events ( status TEXT, FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); + +-- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). +CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx + ON corsair_accounts (tenant_id, integration_id); +CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx + ON corsair_entities (account_id, entity_type, entity_id); ``` From 209ea20b87ce760f012a77085827bfea5ab4d262 Mon Sep 17 00:00:00 2001 From: ambikeesshh Date: Thu, 27 Aug 2026 11:04:58 +0530 Subject: [PATCH 2/6] docs(db): index drizzle and prisma schema examples --- docs/concepts/database.mdx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/concepts/database.mdx b/docs/concepts/database.mdx index 3b89f2747..1267dc5b3 100644 --- a/docs/concepts/database.mdx +++ b/docs/concepts/database.mdx @@ -9,7 +9,7 @@ Every API call and webhook that flows through Corsair is stored in your database ## Get started -Run the migration once, then pass your connection to `createCorsair({ database, ... })`. See [Quick Start](/quick-start) for a full setup example. +Run the migration once, then pass your connection to `createCorsair({ database, ... })`. See [Quick Start](/quick-start) for a full setup example. If the tables already exist, run only the two `CREATE INDEX` statements. @@ -146,7 +146,6 @@ CREATE TABLE IF NOT EXISTS corsair_permissions ( error TEXT ); --- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx ON corsair_accounts (tenant_id, integration_id); CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx @@ -239,7 +238,6 @@ CREATE TABLE IF NOT EXISTS corsair_permissions ( error TEXT ); --- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx ON corsair_accounts (tenant_id, integration_id); CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx @@ -275,7 +273,7 @@ psql $env:DATABASE_URL -f migration.sql ```ts src/server/db/schema.ts -import { pgTable, text, jsonb, timestamp } from 'drizzle-orm/pg-core'; +import { pgTable, text, jsonb, timestamp, index } from 'drizzle-orm/pg-core'; export const corsairIntegrations = pgTable('corsair_integrations', { id: text('id').primaryKey(), @@ -294,7 +292,9 @@ export const corsairAccounts = pgTable('corsair_accounts', { integrationId: text('integration_id').notNull().references(() => corsairIntegrations.id), config: jsonb('config').notNull().default({}), dek: text('dek'), -}); +}, (table) => [ + index('corsair_accounts_tenant_integration_idx').on(table.tenantId, table.integrationId), +]); export const corsairEntities = pgTable('corsair_entities', { id: text('id').primaryKey(), @@ -305,7 +305,9 @@ export const corsairEntities = pgTable('corsair_entities', { entityType: text('entity_type').notNull(), version: text('version').notNull(), data: jsonb('data').notNull().default({}), -}); +}, (table) => [ + index('corsair_entities_account_type_entity_idx').on(table.accountId, table.entityType, table.entityId), +]); export const corsairEvents = pgTable('corsair_events', { id: text('id').primaryKey(), @@ -372,6 +374,7 @@ model CorsairAccount { entities CorsairEntity[] events CorsairEvent[] + @@index([tenantId, integrationId], map: "corsair_accounts_tenant_integration_idx") @@map("corsair_accounts") } @@ -386,6 +389,7 @@ model CorsairEntity { data Json @default("{}") account CorsairAccount @relation(fields: [accountId], references: [id]) + @@index([accountId, entityType, entityId], map: "corsair_entities_account_type_entity_idx") @@map("corsair_entities") } From 9fd384e91c5f9df84e2039117ac7ff2548796571 Mon Sep 17 00:00:00 2001 From: ambikeesshh Date: Thu, 27 Aug 2026 11:05:03 +0530 Subject: [PATCH 3/6] docs: note CREATE INDEX for existing installs --- docs/guides/dashboard.mdx | 3 ++- docs/quick-start.mdx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/guides/dashboard.mdx b/docs/guides/dashboard.mdx index df5ebf654..9af287a80 100644 --- a/docs/guides/dashboard.mdx +++ b/docs/guides/dashboard.mdx @@ -177,7 +177,6 @@ CREATE TABLE IF NOT EXISTS corsair_events ( FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); --- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx ON corsair_accounts (tenant_id, integration_id); CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx @@ -206,6 +205,8 @@ Get-Content migration.sql | sqlite3 corsair.db +If the tables already exist, run only the two `CREATE INDEX` statements. + diff --git a/docs/quick-start.mdx b/docs/quick-start.mdx index a9e8193b2..f09ef1186 100644 --- a/docs/quick-start.mdx +++ b/docs/quick-start.mdx @@ -137,7 +137,6 @@ CREATE TABLE IF NOT EXISTS corsair_permissions ( error TEXT ); --- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx ON corsair_accounts (tenant_id, integration_id); CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx @@ -165,6 +164,8 @@ Get-Content migration.sql | sqlite3 corsair.db +If the tables already exist, run only the two `CREATE INDEX` statements. + Using Postgres, Drizzle, or Prisma instead? See [Database](/concepts/database) for each option. From c3d593f6952c14b284d05ac317bd2e21914ba9f3 Mon Sep 17 00:00:00 2001 From: ambikeesshh Date: Thu, 27 Aug 2026 11:05:03 +0530 Subject: [PATCH 4/6] fix(demo): index accounts and entities in drizzle --- .../drizzle/0001_entities_account_index.sql | 2 + demo/testing/drizzle/meta/0001_snapshot.json | 377 ++++++++++++++++++ demo/testing/drizzle/meta/_journal.json | 9 +- demo/testing/src/db/schema.ts | 87 ++-- 4 files changed, 440 insertions(+), 35 deletions(-) create mode 100644 demo/testing/drizzle/0001_entities_account_index.sql create mode 100644 demo/testing/drizzle/meta/0001_snapshot.json diff --git a/demo/testing/drizzle/0001_entities_account_index.sql b/demo/testing/drizzle/0001_entities_account_index.sql new file mode 100644 index 000000000..3922dff17 --- /dev/null +++ b/demo/testing/drizzle/0001_entities_account_index.sql @@ -0,0 +1,2 @@ +CREATE INDEX `corsair_accounts_tenant_integration_idx` ON `corsair_accounts` (`tenant_id`,`integration_id`);--> statement-breakpoint +CREATE INDEX `corsair_entities_account_type_entity_idx` ON `corsair_entities` (`account_id`,`entity_type`,`entity_id`); diff --git a/demo/testing/drizzle/meta/0001_snapshot.json b/demo/testing/drizzle/meta/0001_snapshot.json new file mode 100644 index 000000000..fa71cd524 --- /dev/null +++ b/demo/testing/drizzle/meta/0001_snapshot.json @@ -0,0 +1,377 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "303100e3-b988-44e0-9bab-73bdaa722aaa", + "prevId": "a5e0ee72-cd9f-4f83-b44b-d0ebc1b17246", + "tables": { + "corsair_accounts": { + "name": "corsair_accounts", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "integration_id": { + "name": "integration_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config": { + "name": "config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dek": { + "name": "dek", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "corsair_accounts_tenant_integration_idx": { + "name": "corsair_accounts_tenant_integration_idx", + "columns": ["tenant_id", "integration_id"], + "isUnique": false + } + }, + "foreignKeys": { + "corsair_accounts_integration_id_corsair_integrations_id_fk": { + "name": "corsair_accounts_integration_id_corsair_integrations_id_fk", + "tableFrom": "corsair_accounts", + "tableTo": "corsair_integrations", + "columnsFrom": ["integration_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "corsair_entities": { + "name": "corsair_entities", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "corsair_entities_account_type_entity_idx": { + "name": "corsair_entities_account_type_entity_idx", + "columns": ["account_id", "entity_type", "entity_id"], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "corsair_events": { + "name": "corsair_events", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "corsair_integrations": { + "name": "corsair_integrations", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "config": { + "name": "config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dek": { + "name": "dek", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "corsair_permissions": { + "name": "corsair_permissions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin": { + "name": "plugin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "endpoint": { + "name": "endpoint", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "args": { + "name": "args", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "callback_url": { + "name": "callback_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "review_url": { + "name": "review_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tenant_id": { + "name": "tenant_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} diff --git a/demo/testing/drizzle/meta/_journal.json b/demo/testing/drizzle/meta/_journal.json index 2e34c00ea..8c5df41f3 100644 --- a/demo/testing/drizzle/meta/_journal.json +++ b/demo/testing/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1773529091251, "tag": "0000_nasty_moondragon", "breakpoints": true + }, + { + "idx": 1, + "version": "6", + "when": 1787808505608, + "tag": "0001_entities_account_index", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/demo/testing/src/db/schema.ts b/demo/testing/src/db/schema.ts index 8cf1a6dd3..436dc44ed 100644 --- a/demo/testing/src/db/schema.ts +++ b/demo/testing/src/db/schema.ts @@ -1,4 +1,4 @@ -import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; +import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; export const corsair_integrations = sqliteTable('corsair_integrations', { id: text('id') @@ -15,40 +15,59 @@ export const corsair_integrations = sqliteTable('corsair_integrations', { dek: text('dek'), }); -export const corsair_accounts = sqliteTable('corsair_accounts', { - id: text('id') - .primaryKey() - .$defaultFn(() => crypto.randomUUID()), - created_at: integer('created_at', { mode: 'timestamp' }) - .notNull() - .$defaultFn(() => new Date()), - updated_at: integer('updated_at', { mode: 'timestamp' }) - .notNull() - .$defaultFn(() => new Date()), - tenant_id: text('tenant_id').notNull(), - integration_id: text('integration_id') - .notNull() - .references(() => corsair_integrations.id), - config: text('config', { mode: 'json' }), - dek: text('dek'), -}); +export const corsair_accounts = sqliteTable( + 'corsair_accounts', + { + id: text('id') + .primaryKey() + .$defaultFn(() => crypto.randomUUID()), + created_at: integer('created_at', { mode: 'timestamp' }) + .notNull() + .$defaultFn(() => new Date()), + updated_at: integer('updated_at', { mode: 'timestamp' }) + .notNull() + .$defaultFn(() => new Date()), + tenant_id: text('tenant_id').notNull(), + integration_id: text('integration_id') + .notNull() + .references(() => corsair_integrations.id), + config: text('config', { mode: 'json' }), + dek: text('dek'), + }, + (table) => [ + index('corsair_accounts_tenant_integration_idx').on( + table.tenant_id, + table.integration_id, + ), + ], +); -export const corsair_entities = sqliteTable('corsair_entities', { - id: text('id') - .primaryKey() - .$defaultFn(() => crypto.randomUUID()), - created_at: integer('created_at', { mode: 'timestamp' }) - .notNull() - .$defaultFn(() => new Date()), - updated_at: integer('updated_at', { mode: 'timestamp' }) - .notNull() - .$defaultFn(() => new Date()), - account_id: text('account_id').notNull(), - entity_id: text('entity_id').notNull(), - entity_type: text('entity_type').notNull(), - version: text('version').notNull(), - data: text('data', { mode: 'json' }).notNull(), -}); +export const corsair_entities = sqliteTable( + 'corsair_entities', + { + id: text('id') + .primaryKey() + .$defaultFn(() => crypto.randomUUID()), + created_at: integer('created_at', { mode: 'timestamp' }) + .notNull() + .$defaultFn(() => new Date()), + updated_at: integer('updated_at', { mode: 'timestamp' }) + .notNull() + .$defaultFn(() => new Date()), + account_id: text('account_id').notNull(), + entity_id: text('entity_id').notNull(), + entity_type: text('entity_type').notNull(), + version: text('version').notNull(), + data: text('data', { mode: 'json' }).notNull(), + }, + (table) => [ + index('corsair_entities_account_type_entity_idx').on( + table.account_id, + table.entity_type, + table.entity_id, + ), + ], +); export const corsair_events = sqliteTable('corsair_events', { id: text('id') From f1264d3cbe7fd3e59cb56e8072f977dd4f6390e6 Mon Sep 17 00:00:00 2001 From: ambikeesshh Date: Thu, 27 Aug 2026 11:05:03 +0530 Subject: [PATCH 5/6] chore(demo): drop covering-index sql comment --- demo/testing/migration.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/testing/migration.sql b/demo/testing/migration.sql index b66e20299..1f0a5c168 100644 --- a/demo/testing/migration.sql +++ b/demo/testing/migration.sql @@ -41,7 +41,6 @@ CREATE TABLE IF NOT EXISTS corsair_events ( FOREIGN KEY (account_id) REFERENCES corsair_accounts(id) ); --- Indexes covering the sync-layer hot paths (account lookup + entity upsert/read). CREATE INDEX IF NOT EXISTS corsair_accounts_tenant_integration_idx ON corsair_accounts (tenant_id, integration_id); CREATE INDEX IF NOT EXISTS corsair_entities_account_type_entity_idx From 750aa224f0bcde76359d444cdb6745ea5b635646 Mon Sep 17 00:00:00 2001 From: ambikeesshh Date: Thu, 27 Aug 2026 11:09:14 +0530 Subject: [PATCH 6/6] style(demo): add trailing newline to drizzle journal --- demo/testing/drizzle/meta/_journal.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/testing/drizzle/meta/_journal.json b/demo/testing/drizzle/meta/_journal.json index 8c5df41f3..33cd67ce6 100644 --- a/demo/testing/drizzle/meta/_journal.json +++ b/demo/testing/drizzle/meta/_journal.json @@ -17,4 +17,4 @@ "breakpoints": true } ] -} \ No newline at end of file +}