Skip to content

Refactor: Cache manifest and init data to reduce cold-start queries#378

Open
gruntlord5 wants to merge 5 commits intoemdash-cms:mainfrom
gruntlord5:perf/cold-start-caching
Open

Refactor: Cache manifest and init data to reduce cold-start queries#378
gruntlord5 wants to merge 5 commits intoemdash-cms:mainfrom
gruntlord5:perf/cold-start-caching

Conversation

@gruntlord5
Copy link
Copy Markdown

What does this PR do?

Reduces cold-start database queries from ~20 to ~2 on established sites by caching manifest and init data, deferring migrations to the dialect layer, and skipping FTS verification on init.

Closes #346

Type of change

  • Performance improvement

Changes

Manifest caching

getManifest() checks an in-memory cache, then a DB-persisted cache (1 query), before falling back to the full N+1 schema registry rebuild. invalidateManifest() clears both caches -- it's already called from the MCP server on schema/plugin changes.

Init data caching

Plugin states + site info are cached together in a single options row. On cold start, 1 query replaces 2-4. Site info also uses getMany() (batch WHERE IN) instead of 3 sequential get() calls on cache miss.

Lazy migration dialect wrapper

New wrapWithLazyMigrations() utility wraps any Kysely dialect to defer migration checks until the first schema error (no such table / does not exist). Applied to all built-in adapters (SQLite, libSQL, PostgreSQL, D1). Third-party dialects that don't use the wrapper still get eager migrations as a fallback.

Skip FTS verify on init

FTS corruption is rare; checking every cold start adds latency without benefit on stable sites.

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes (pre-existing failures in admin/core unrelated to this PR -- same on main)
  • pnpm --silent lint:json | jq '.diagnostics | length' returns 14 (down from 16 on main -- we removed 2 unused imports)
  • pnpm test passes (1829 passed, 18 pre-existing failures same on main)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion: Reduce cold start queries by caching init data and deferring checks #346

AI-generated code disclosure

  • This PR includes AI-generated code

Screenshots / test output

Build passes for both emdash and @emdash-cms/cloudflare. Test suite: 1829 tests passed, 18 pre-existing failures (identical to clean main). Lint diagnostics reduced from 16 to 14 (removed 2 unused imports from FTS verify removal).

gruntlord5 and others added 4 commits April 8, 2026 06:28
Cold starts currently run ~20 database queries before the first page
can render (FTS verify, 32+ migration checks, 3 sequential site info
queries, N+1 manifest rebuild). Most of this produces the same result
every time and only needs to rerun when an admin changes something.

This commit reduces cold-start queries from ~20 to ~2:

1. **Manifest caching**: getManifest() now checks an in-memory cache,
   then a DB-persisted cache (1 query), before falling back to the
   full N+1 rebuild. invalidateManifest() clears both caches and is
   already called from the MCP server on schema/plugin changes.

2. **Init data caching**: Plugin states + site info are cached together
   in a single options row. On cold start, 1 query replaces 2-4.
   Site info uses getMany() (batch WHERE IN) instead of 3 sequential
   get() calls even on cache miss.

3. **Lazy migration wrapper**: New wrapWithLazyMigrations() dialect
   wrapper defers migration checks until the first schema error. On
   established sites the schema is stable, so checking 30+ migrations
   on every cold start is pure overhead. Fresh installs and upgrades
   are handled automatically when the first query hits "no such table".
   Applied to all built-in adapters (SQLite, libSQL, PostgreSQL, D1).
   Third-party dialects that don't use the wrapper still get eager
   migrations as a fallback.

4. **Skip FTS verify on init**: FTS corruption is rare; checking every
   cold start adds latency without benefit on stable sites.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cold starts currently run ~20 database queries before the first page
can render (FTS verify, 32+ migration checks, 3 sequential site info
queries, N+1 manifest rebuild). Most of this produces the same result
every time and only needs to rerun when an admin changes something.

This commit reduces cold-start queries from ~20 to ~2:

1. **Manifest caching**: getManifest() now checks an in-memory cache,
   then a DB-persisted cache (1 query), before falling back to the
   full N+1 rebuild. invalidateManifest() clears both caches and is
   already called from the MCP server on schema/plugin changes.

2. **Init data caching**: Plugin states + site info are cached together
   in a single options row. On cold start, 1 query replaces 2-4.
   Site info uses getMany() (batch WHERE IN) instead of 3 sequential
   get() calls even on cache miss.

3. **Lazy migration wrapper**: New wrapWithLazyMigrations() dialect
   wrapper defers migration checks until the first schema error. On
   established sites the schema is stable, so checking 30+ migrations
   on every cold start is pure overhead. Fresh installs and upgrades
   are handled automatically when the first query hits "no such table".
   Applied to all built-in adapters (SQLite, libSQL, PostgreSQL, D1).
   Third-party dialects that don't use the wrapper still get eager
   migrations as a fallback.

4. **Skip FTS verify on init**: FTS corruption is rare; checking every
   cold start adds latency without benefit on stable sites.
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

🦋 Changeset detected

Latest commit: ebbdf34

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
emdash Minor
@emdash-cms/cloudflare Minor
@emdash-cms/plugin-ai-moderation Major
@emdash-cms/plugin-atproto Patch
@emdash-cms/plugin-audit-log Patch
@emdash-cms/plugin-color Major
@emdash-cms/plugin-embeds Major
@emdash-cms/plugin-forms Major
@emdash-cms/plugin-webhook-notifier Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@gruntlord5
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

github-actions bot added a commit that referenced this pull request Apr 8, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 9, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@378

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@378

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@378

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@378

emdash

npm i https://pkg.pr.new/emdash@378

create-emdash

npm i https://pkg.pr.new/create-emdash@378

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@378

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@378

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@378

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@378

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@378

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@378

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@378

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@378

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@378

commit: ebbdf34

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants