Skip to content

[recipes] Edge function cost optimization — 73% invocation reduction#188

Merged
justfinethanku merged 2 commits into
NateBJones-Projects:mainfrom
JustinTSmith:contrib/JustinTSmith/edge-fn-cost-optimization
May 22, 2026
Merged

[recipes] Edge function cost optimization — 73% invocation reduction#188
justfinethanku merged 2 commits into
NateBJones-Projects:mainfrom
JustinTSmith:contrib/JustinTSmith/edge-fn-cost-optimization

Conversation

@JustinTSmith

Copy link
Copy Markdown
Contributor

Contribution Type

  • Recipe (/recipes)
  • Schema (/schemas)
  • Dashboard (/dashboards)
  • Integration (/integrations)
  • Skill (/skills)
  • Repo improvement (docs, CI, templates)

What does this do?

Adds a recipe that cuts Supabase Edge Function invocations ~73% by combining three fixes the repo doesn't currently address: consolidating multiple per-extension MCP edge functions into a single function, adding Mcp-Session-Id reuse so the 4-step MCP handshake collapses into a single tools/call within a warm window, and caching hot read paths (with a new SQL aggregation RPC that replaces a JS-side full-table scan in thought_stats).

Measured impact on a real OB1 deployment running the four canonical extensions: 1,835,479 → ~440,000 invocations/month projected — comfortably under the 500K free-tier cap.

Why this matters

The repo's architecture (CLAUDE.md: "MCP servers must be remote — Supabase Edge Functions, one per extension") is correct, but the default StreamableHTTPTransport from @hono/mcp is stateless and the repo has no recipe addressing the resulting invocation cost. Real users hitting the free-tier cap have no documented path forward besides upgrading. A search of issues, discussions, and existing recipes/primitives at the time of authoring turned up no prior work on this — see Substack/podcast archive, all open + closed issues, all existing recipes.

The three fixes are independent and additive:

  1. Consolidate N → 1 edge function. Tools are uniquely named across extensions; nothing requires separate functions. One Hono app + one module-scope McpServer + per-extension register(server) modules. 4 connectors → 1 connector cuts startup invocations 4×.
  2. Mcp-Session-Id reuse. Module-scope Map<sid, Session> + Access-Control-Expose-Headers: mcp-session-id collapses the initialize/notifications-initialized/tools-list handshake within a warm session. 1 user-visible tool call → 1 HTTP invocation on a warm session.
  3. Cache hot read paths + SQL aggregation. TTL cache with tag-based invalidation. New thought_stats_summary() SQL RPC replaces a full-table scan with a single aggregation query. New upsert_thought(text, jsonb, vector) overload writes content + embedding in one round-trip instead of two (the existing 2-arg signature is preserved).

Requirements

  • Working Open Brain setup
  • Supabase CLI + Deno 2.x to deploy
  • The two new SQL functions (thought_stats_summary, 3-arg upsert_thought) in migrations/20260417_edge_fn_optimizations.sql — both additive, no schema changes

Builds on:

What's in the recipe

  • README.md — problem statement, the three fixes with rationale, measured impact, step-by-step migration guide, troubleshooting
  • metadata.json — schema-compliant
  • examples/before/per-request-server.ts — the per-request anti-pattern (annotated)
  • examples/after/server.ts — the singleton McpServer pattern
  • examples/after/index.ts — the session-reuse Hono handler
  • examples/after/cache.ts — the TTL + tag-invalidation cache
  • examples/after/410-stub.ts — a redirect stub for deprecated functions
  • migrations/20260417_edge_fn_optimizations.sql — both new RPCs

Test plan

  • Recipe README has prerequisites, step-by-step instructions, and expected outcome
  • metadata.json validates against .github/metadata.schema.json
  • No credentials, API keys, or secrets included
  • All example .ts files pass deno check (verified against npm:@hono/mcp@0.1.1 + npm:@modelcontextprotocol/sdk@1.24.3 + npm:hono@4.9.2)
  • End-to-end verified on a live deployment (5,806 thoughts, 4 extensions consolidated, 22 tools registered):
    • initialize returns Mcp-Session-Id header
    • tools/list with reused session enumerates all 22 tools
    • thought_stats returns aggregated results via the new SQL RPC (full table scan eliminated)
    • One tool from each former extension (list_vendors, search_recipes, get_follow_ups_due) works through the unified endpoint
    • Old function URLs return HTTP 410 Gone with redirect hint

Checklist

  • I've read CONTRIBUTING.md
  • My contribution has a README.md with prerequisites, step-by-step instructions, and expected outcome
  • My metadata.json has all required fields
  • If my contribution depends on a skill or primitive, I declared it in metadata.json and linked it in the README
  • I tested this on my own Open Brain instance
  • No credentials, API keys, or secrets are included

🤖 Generated with Claude Code

Cuts Supabase Edge Function invocations ~73% by combining three fixes:

1. Consolidate N MCP edge functions into 1 (each connector multiplies the
   4-step MCP handshake; one connector + module-scope McpServer cuts
   startup invocations 4x for 4 extensions)
2. Add Mcp-Session-Id reuse so the initialize/notifications/tools-list
   handshake collapses into a single tools/call within a warm window
3. Cache hot read paths (thought_stats via new SQL aggregation RPC,
   query embeddings, list_vendors, get_follow_ups_due) with tag-based
   invalidation; new upsert_thought(text, jsonb, vector) RPC overload
   eliminates the separate UPDATE for embeddings

Measured: 1.84M → ~440K invocations/month projected on a real OB1
deployment with the four canonical extensions.

Includes: README walkthrough, before/after example snippets,
metadata.json, and the SQL migrations for the two new RPCs (additive,
non-breaking).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added the recipe Contribution: step-by-step recipe label Apr 17, 2026
@github-actions

Copy link
Copy Markdown

Hey @JustinTSmith — welcome to Open Brain Source! 👋

Thanks for submitting your first PR. The automated review will run shortly and check things like metadata, folder structure, and README completeness. If anything needs fixing, the review comment will tell you exactly what.

Once the automated checks pass, a human admin will review for quality and clarity. Expect a response within a few days.

If you have questions, check out CONTRIBUTING.md or open an issue.

@alanshurafa alanshurafa added area: recipes Review area: recipes review: ready-for-maintainer Community reviewer recommends maintainer review alan-reviewed Reviewed by Alan Shurafa in Community Reviewer role labels May 20, 2026
@alanshurafa

Copy link
Copy Markdown
Collaborator

Thanks for the contribution, and welcome. This is a well-structured cost-optimization recipe — consolidating per-extension MCP functions into one, Mcp-Session-Id reuse to collapse the handshake, and a cache layer, with before/after example code and a clean 410-stub transition for the deprecated functions. The migration is additive (creates two functions, no schema change), as the README states.

Worth noting it overlaps conceptually with #261, which fixes per-request McpServer instantiation in the core server — #188's examples/before/per-request-server.ts is the same anti-pattern. They are complementary (recipe guidance vs core fix). Recommend maintainer review.

— Alan (community reviewer; non-binding)

@justfinethanku
justfinethanku merged commit f5457ee into NateBJones-Projects:main May 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

alan-reviewed Reviewed by Alan Shurafa in Community Reviewer role area: recipes Review area: recipes recipe Contribution: step-by-step recipe review: ready-for-maintainer Community reviewer recommends maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants