Skip to content

FE-1569: Add durable Brunch storage and telemetry - #9487

Open
lunelson wants to merge 10 commits into
ln/fe-1569-brunch-agent-containerfrom
ln/fe-1569-brunch-agent-deployment
Open

FE-1569: Add durable Brunch storage and telemetry#9487
lunelson wants to merge 10 commits into
ln/fe-1569-brunch-agent-containerfrom
ln/fe-1569-brunch-agent-deployment

Conversation

@lunelson

@lunelson lunelson commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

🌟 What is the purpose of this PR?

Add the runtime behavior needed to take the containerized Brunch service to the application-to-infrastructure deployment boundary: durable Flue Postgres state, content-free operational telemetry, and explicit diagnostics for restricted deployment and recovery.

This PR does not claim that Brunch is deployed. The downstack container PR publishes to ECR and GHCR, but no Brunch ECS service, RDS target, hosted collector, restricted ingress, or deployment owner is confirmed, so Mission 8 remains open at its required handoff boundary.

🔗 Related links

🚫 Blocked by

  • Infrastructure owner confirms and provisions the Brunch ECS, RDS/IAM, collector, restricted ingress, and deployment-owner targets.
  • The remote Mission 8 proof matrix passes against one immutable image digest.

🔍 What does this change?

  • Replaces deployed SQLite with fail-closed @flue/postgres persistence using dedicated fields, verified TLS, RDS IAM tokens per physical connection, and a runtime-password fallback.
  • Adds content-free Flue and Node OpenTelemetry export over OTLP/gRPC with graceful lifecycle flush and operational database-failure spans.
  • Adds RDS IAM and restricted deployment probes plus a disposable TLS Postgres/OTel container smoke.
  • Documents runtime configuration, ingress restrictions, local proof, GHCR publication, and the outstanding infrastructure handoff.
🏗️ Agent notes

The branch authority is libs/@hashintel/brunch-agent/MISSION.md. It records Mission 8 as live but stopped at the explicit application-to-infrastructure handoff boundary.

Locally established:

  • fail-closed production configuration and Flue Postgres migration before listen;
  • IAM-token callback refresh, transaction pinning/rollback, TLS verification, and static-password fallback;
  • content-free OTLP traces, logs, and metrics with graceful shutdown;
  • disposable TLS Postgres and OTel collector integration smoke.

Still open:

  • real task-role/RDS IAM connectivity;
  • restricted streamed Anthropic/tool execution;
  • in-place and cross-host replacement recovery;
  • bounded provider/database/stream failure inspection in the hosted telemetry backend;
  • singleton replacement, rollback, and owner acceptance.

The downstack PR registers ECR and GHCR publication with no ECS target. Infrastructure provisioning and remote proof remain outside this local application artifact.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • require changes to docs which are made as part of this PR

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • affected the execution graph, and the turbo.json files have been updated to reflect this

⚠️ Known issues

  • Brunch is not deployed; the deploy catalog publishes to ECR and GHCR but has no ECS target.
  • The local Docker smoke uses the runtime-password path; the real task-role RDS IAM probe remains unrun.
  • /health proves process liveness only. Database connection and migration gate startup before the server listens.
  • Public identity, authorization, rate/spend controls, retention/deletion policy, backup restoration, and multi-replica ownership remain outside this restricted singleton threshold.

🐾 Next steps

  • Provision and record the ECS, RDS/IAM, secret, collector, ingress, health, timeout, drain, and ownership contract from the deployment handoff.
  • Run the remote proof matrix with one immutable digest and update this PR, Mission 8, and FE-1569 with observed results.

🛡 What tests cover this?

  • 80 Vitest unit tests covering configuration, IAM token refresh, Postgres transactions, health, telemetry lifecycle, artifact wiring, and existing Brunch behavior.
  • TypeScript typecheck, application build, and Oxlint with eight pre-existing warnings and no errors.
  • The previously completed Docker integration smoke covers TLS Postgres migration/startup, fail-closed configuration, OTel export, non-root identity, packaged resources, repository immutability, health, and graceful shutdown.

❓ How to test this?

  1. Run yarn workspace @apps/brunch-agent lint:tsc.
  2. Run yarn workspace @apps/brunch-agent test:unit.
  3. Run yarn workspace @apps/brunch-agent build.
  4. Run turbo run test:docker --filter @apps/brunch-agent with Docker available.
  5. After infrastructure exists, follow apps/brunch-agent/README.md and the Mission 8 deployment handoff for the IAM and remote smoke commands.

📹 Demo

No visual UI change. The proof artifact is the production container and its deployment diagnostics.

@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hash Ready Ready Preview Sep 4, 2026 4:43pm UTC
hashdotdesign-tokens Ready Ready Preview Sep 4, 2026 4:43pm UTC
petrinaut Ready Ready Preview Sep 4, 2026 4:43pm UTC
petrinaut-docs Ready Ready Preview Sep 4, 2026 4:43pm UTC

Request Review

@github-actions github-actions Bot added area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/tests New or updated tests area/apps labels Sep 1, 2026
Comment thread apps/brunch-agent/src/postgres.ts Fixed
@codspeed-hq

codspeed-hq Bot commented Sep 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 6 benchmarks measured no execution time

Nothing ran under measurement, usually because the compiler removed the code under test. These results are not comparable, so they count as unchanged.

Preventing compiler optimizations

✅ 98 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
⚠️ as_constant < 1 ns < 1 ns N/A
⚠️ constant_equal < 1 ns < 1 ns N/A
⚠️ constant_not_equal < 1 ns < 1 ns N/A
⚠️ access < 1 ns < 1 ns N/A
⚠️ runtime_equal < 1 ns < 1 ns N/A
⚠️ runtime_not_equal < 1 ns < 1 ns N/A

Comparing ln/fe-1569-brunch-agent-deployment (c079ffb) with ln/fe-1569-brunch-agent-container (9144fc8)

Open in CodSpeed

lunelson commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@TimDiekmann TimDiekmann left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if we could isolate the Dockerfile changes into an own PR. The changes to .github/workflows/deploy.yml will make sure that the build is covered in CI and will upload it on merge to main. I will make sure that a ECR is set up where we can upload the image to and extend the definition with that.

Comment thread apps/brunch-agent/package.json
Comment thread apps/brunch-agent/docker/Dockerfile
@lunelson
lunelson changed the base branch from ln/fe-1563-redesign-runbook-workpiece to graphite-base/9487 September 2, 2026 11:12
@lunelson
lunelson force-pushed the ln/fe-1569-brunch-agent-deployment branch from 157730c to a118473 Compare September 2, 2026 11:12
@lunelson
lunelson changed the base branch from graphite-base/9487 to ln/fe-1569-brunch-agent-container September 2, 2026 11:12
@lunelson lunelson changed the title FE-1569: Containerize and safely deploy Brunch on HASH infrastructure FE-1569: Add durable Brunch storage and telemetry Sep 2, 2026
@vercel
vercel Bot temporarily deployed to Preview – petrinaut September 2, 2026 11:13 Inactive
@cursor

cursor Bot commented Sep 4, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes production conversation durability, RDS IAM/password database auth, and mandatory telemetry export—misconfiguration or pool/IAM bugs would block startup or lose chat state.

Overview
Adds the production deployment runtime for containerized Brunch: Flue conversation state moves from local SQLite to Postgres when NODE_ENV=production, driven by dedicated BRUNCH_POSTGRES_* settings (RDS IAM or password), mandatory TLS, legacy DATABASE_URL/SQLite env rejection, and a 10s connection timeout. Startup wires @flue/postgres through a new pg pool/runner with transaction pinning, IAM token refresh per physical connection, and an probe:rds-iam CLI for task-role verification.

Telemetry moves out of app.ts into an early telemetry-bootstrap that registers content-free Flue OTel plus HASH OTLP/gRPC traces/logs/metrics (required HASH_OTLP_ENDPOINT in production), operational failure spans, and coordinated shutdown with Postgres close.

New operational scripts and tests: start/start:test with health waits, smoke:deployment (streamed turn + persisted history check), disposable test:docker Postgres/OTel container smoke, split unit vs integration Vitest, and build-artifact assertions for fail-closed production wiring. README and Mission 8 handoff document the container contract, ingress restrictions, and infra still required before ECS deploy.

Reviewed by Cursor Bugbot for commit c079ffb. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Moderate issues remain in recovery validation, database timeouts, and Flue telemetry export.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds durable PostgreSQL persistence, RDS IAM support, operational telemetry, and deployment diagnostics for the Brunch service.

Changes:

  • Adds fail-closed PostgreSQL configuration with TLS and IAM/password authentication.
  • Adds OTLP telemetry lifecycle and database-failure reporting.
  • Adds deployment probes, integration tests, and infrastructure handoff documentation.
File summaries
File Review
yarn.lock Locks new database, AWS, and telemetry dependencies.
libs/@hashintel/brunch-agent/MISSION.next.md Updates deployment backlog and planning context.
libs/@hashintel/brunch-agent/MISSION.md Defines the restricted-deployment mission.
libs/@hashintel/brunch-agent/docs/evidence/implementations/mission-8-deployment-handoff.md Records proof status and infrastructure handoff.
apps/brunch-agent/turbo.json Adds telemetry environment and integration-test wiring.
apps/brunch-agent/test/telemetry.test.ts Tests telemetry configuration and disposal.
apps/brunch-agent/test/postgres.test.ts Tests pooling, IAM tokens, transactions, and shutdown.
apps/brunch-agent/test/database-config.test.ts Tests production database validation.
apps/brunch-agent/test/container-smoke.integration.ts Exercises the production container with PostgreSQL and OTel.
apps/brunch-agent/test/build-artifact.test.ts Verifies persistence and telemetry bundle wiring.
apps/brunch-agent/test/architecture/boundaries.integration.ts Registers the telemetry architecture boundary.
apps/brunch-agent/src/telemetry.ts Configures OTLP providers and failure spans. Moderate (1 vote): Flue metrics use the unregistered global meter and are not exported. Moderate (1 vote): Flue also receives no logger, dropping its logs as well as metrics.
apps/brunch-agent/src/telemetry-bootstrap.ts Installs telemetry before application initialization.
apps/brunch-agent/src/rds-iam-probe.ts Adds the two-connection IAM diagnostic.
apps/brunch-agent/src/postgres.ts Implements the Flue PostgreSQL runner. Moderate (1 vote): No connection timeout is configured, allowing database operations and diagnostics to wait indefinitely.
apps/brunch-agent/src/deployment-smoke.ts Adds remote turn and history diagnostics. Moderate (2 votes): Recovery can report success for missing/malformed history, and streamed turns do not require a successful finish.
apps/brunch-agent/src/db.ts Selects PostgreSQL in production and SQLite locally.
apps/brunch-agent/src/database-config.ts Defines fail-closed production database configuration.
apps/brunch-agent/src/app.ts Bootstraps telemetry before route setup.
apps/brunch-agent/README.md Documents runtime and deployment requirements.
apps/brunch-agent/package.json Adds dependencies and operational scripts.
apps/brunch-agent/docs/task-dependencies.json Documents the new task dependencies.
Review details

Suppressed comments (4)

apps/brunch-agent/src/postgres.ts:102

  • A pg pool emits an error event when an idle connection is broken; without a listener, Node treats that event as unhandled and terminates the process. A routine RDS restart or network partition can therefore crash Brunch instead of producing the operational database-failure telemetry added by this PR. Attach a pool error listener and report it through reportDatabaseFailure.
export const createPostgresPool = (
  config: PostgresDatabaseConfig,
  options?: ConnectionOptions,
): Pool => new Pool(createPostgresPoolConfig(config, options));

apps/brunch-agent/src/postgres.ts:200

  • If one pool.connect() resolves and the other rejects, the Promise.all assignment never completes, so clients remains empty and the successful checked-out client is omitted from the finally cleanup. The failed IAM probe then leaks that client and can leave pool.end() waiting indefinitely. Acquire while appending each client (the first remains checked out, so the second is still guaranteed to be a distinct physical connection).
  let clients: PoolClient[] = [];
  try {
    clients = await Promise.all([pool.connect(), pool.connect()]);

apps/brunch-agent/src/postgres.ts:128

  • A transaction that fails while acquiring a pooled connection bypasses the try block, so no database_operation failure span is recorded. This is the exact path taken when Postgres is unavailable during Flue startup/migration, contradicting the operational database-failure telemetry contract. Report and rethrow acquisition failures before entering the transaction body.
      const client = await pool.connect();

apps/brunch-agent/src/postgres.ts:156

  • Both expressions passed to Promise.allSettled are invoked immediately, so telemetry shutdown begins before pool.end() has completed. The unit test only observes synchronous mock side effects and therefore does not enforce the documented “close Postgres, then flush OTel” lifecycle; with a real pool, final database activity can race provider shutdown. Await the Postgres result first, then invoke the telemetry closer while still collecting both failures.
      const results = await Promise.allSettled([pool.end(), afterClose?.()]);
  • Files reviewed: 21/22 changed files
  • Comments generated: 4
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/brunch-agent/src/deployment-smoke.ts Outdated
Comment thread apps/brunch-agent/src/postgres.ts
Comment thread apps/brunch-agent/src/telemetry.ts
Comment thread apps/brunch-agent/src/telemetry.ts Outdated
Comment thread apps/brunch-agent/src/telemetry.ts
Comment thread apps/brunch-agent/src/database-config.ts
Comment thread apps/brunch-agent/src/deployment-smoke.ts
Comment thread apps/brunch-agent/src/postgres.ts
lunelson and others added 8 commits September 4, 2026 14:23
Co-authored-by: Cursor <cursoragent@cursor.com>

Normalize deployment dependency lockfile

Co-authored-by: Cursor <cursoragent@cursor.com>

Publish the Brunch image to GHCR

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread apps/brunch-agent/src/postgres.ts Outdated
Comment thread apps/brunch-agent/src/postgres.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread apps/brunch-agent/src/postgres.ts Dismissed
@lunelson

lunelson commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

@TimDiekmann according to my agent, CI is currently blocked here by an unrelated pruning issue:

  • the workflow initially prunes out @rust/hash-repo-chores
  • the Brunch integration test subsequently performs a nested Docker build
  • that build's turbo prune evaluates turbo.json and encounters the missing @rust/hash-repo-chores#build reference

Failing job: https://github.com/hashintel/hash/actions/runs/33872870612/job/101023099113

FWIW, agent thinks the integration workflow likely needs to retain @rust/hash-repo-chores, as the unit workflow already does. Rerunning the job alone will not fix it... Thoughts?

Comment thread apps/brunch-agent/package.json Outdated
Comment thread apps/brunch-agent/package.json Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c079ffb. Configure here.

"const health = await fetch('http://127.0.0.1:3002/health')",
"if (health.headers.get('content-type') !== 'application/health+json') process.exit(1)",
"if (JSON.stringify(await health.json()) !== JSON.stringify({ status: 'pass' })) process.exit(1)",
"const root = await fetch('http://127.0.0.1:3002/')",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Container port does not match image

High Severity

The container smoke, README, and Mission 8 handoff now treat 3002 as the image listen port, but the image still exposes and health-checks 3000 and never sets PORT. The smoke probes 3002 with no PORT override, so it cannot observe a healthy container, and the handoff can point infrastructure at the wrong port.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c079ffb. Configure here.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$28.9 \mathrm{ms} \pm 258 \mathrm{μs}\left({\color{red}6.18 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.44 \mathrm{ms} \pm 22.1 \mathrm{μs}\left({\color{gray}1.01 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1002 $$12.5 \mathrm{ms} \pm 87.3 \mathrm{μs}\left({\color{gray}1.20 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$43.2 \mathrm{ms} \pm 373 \mathrm{μs}\left({\color{gray}0.349 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.2 \mathrm{ms} \pm 150 \mathrm{μs}\left({\color{gray}-0.675 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1527 $$24.2 \mathrm{ms} \pm 197 \mathrm{μs}\left({\color{gray}0.387 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$29.5 \mathrm{ms} \pm 216 \mathrm{μs}\left({\color{gray}3.70 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.73 \mathrm{ms} \pm 27.5 \mathrm{μs}\left({\color{gray}0.564 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.6 \mathrm{ms} \pm 96.5 \mathrm{μs}\left({\color{gray}1.06 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.79 \mathrm{ms} \pm 22.0 \mathrm{μs}\left({\color{gray}-0.223 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.99 \mathrm{ms} \pm 15.9 \mathrm{μs}\left({\color{gray}-1.359 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 52 $$3.38 \mathrm{ms} \pm 19.8 \mathrm{μs}\left({\color{gray}-1.190 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.31 \mathrm{ms} \pm 40.6 \mathrm{μs}\left({\color{gray}1.43 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.60 \mathrm{ms} \pm 28.4 \mathrm{μs}\left({\color{gray}1.03 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 108 $$4.18 \mathrm{ms} \pm 31.9 \mathrm{μs}\left({\color{gray}1.06 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.52 \mathrm{ms} \pm 39.3 \mathrm{μs}\left({\color{gray}0.009 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.45 \mathrm{ms} \pm 21.9 \mathrm{μs}\left({\color{gray}0.086 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.26 \mathrm{ms} \pm 35.3 \mathrm{μs}\left({\color{gray}1.05 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.76 \mathrm{ms} \pm 21.6 \mathrm{μs}\left({\color{gray}1.64 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.67 \mathrm{ms} \pm 14.4 \mathrm{μs}\left({\color{gray}0.451 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 2 $$2.79 \mathrm{ms} \pm 17.5 \mathrm{μs}\left({\color{gray}-0.359 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$3.06 \mathrm{ms} \pm 19.5 \mathrm{μs}\left({\color{gray}0.739 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.82 \mathrm{ms} \pm 14.4 \mathrm{μs}\left({\color{gray}-1.361 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$3.16 \mathrm{ms} \pm 23.7 \mathrm{μs}\left({\color{gray}1.55 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$3.09 \mathrm{ms} \pm 19.2 \mathrm{μs}\left({\color{gray}-0.102 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.79 \mathrm{ms} \pm 19.2 \mathrm{μs}\left({\color{gray}0.950 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 26 $$2.98 \mathrm{ms} \pm 17.5 \mathrm{μs}\left({\color{gray}0.563 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.56 \mathrm{ms} \pm 20.6 \mathrm{μs}\left({\color{gray}0.452 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.06 \mathrm{ms} \pm 21.1 \mathrm{μs}\left({\color{gray}0.405 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 27 $$3.29 \mathrm{ms} \pm 17.8 \mathrm{μs}\left({\color{gray}-0.334 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.47 \mathrm{ms} \pm 22.3 \mathrm{μs}\left({\color{gray}0.405 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.05 \mathrm{ms} \pm 19.7 \mathrm{μs}\left({\color{gray}0.075 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.36 \mathrm{ms} \pm 19.3 \mathrm{μs}\left({\color{gray}0.767 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$31.2 \mathrm{ms} \pm 181 \mathrm{μs}\left({\color{gray}-0.064 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$70.5 \mathrm{ms} \pm 619 \mathrm{μs}\left({\color{gray}-0.817 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$35.1 \mathrm{ms} \pm 233 \mathrm{μs}\left({\color{gray}0.093 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$39.2 \mathrm{ms} \pm 296 \mathrm{μs}\left({\color{gray}1.59 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$41.0 \mathrm{ms} \pm 281 \mathrm{μs}\left({\color{gray}0.115 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$33.2 \mathrm{ms} \pm 218 \mathrm{μs}\left({\color{gray}0.837 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$421 \mathrm{ms} \pm 1.48 \mathrm{ms}\left({\color{gray}-2.592 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$88.3 \mathrm{ms} \pm 714 \mathrm{μs}\left({\color{gray}4.23 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$78.0 \mathrm{ms} \pm 456 \mathrm{μs}\left({\color{gray}0.580 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$273 \mathrm{ms} \pm 899 \mathrm{μs}\left({\color{lightgreen}-10.035 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$10.2 \mathrm{ms} \pm 66.4 \mathrm{μs}\left({\color{gray}0.328 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$10.5 \mathrm{ms} \pm 83.2 \mathrm{μs}\left({\color{gray}1.69 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$10.5 \mathrm{ms} \pm 73.3 \mathrm{μs}\left({\color{gray}-1.307 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$10.5 \mathrm{ms} \pm 82.6 \mathrm{μs}\left({\color{gray}1.69 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$10.5 \mathrm{ms} \pm 65.8 \mathrm{μs}\left({\color{gray}-0.740 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$10.2 \mathrm{ms} \pm 56.9 \mathrm{μs}\left({\color{gray}-1.004 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$10.4 \mathrm{ms} \pm 86.2 \mathrm{μs}\left({\color{gray}1.06 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$10.8 \mathrm{ms} \pm 86.3 \mathrm{μs}\left({\color{gray}3.91 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$10.8 \mathrm{ms} \pm 76.6 \mathrm{μs}\left({\color{gray}4.34 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$10.8 \mathrm{ms} \pm 86.5 \mathrm{μs}\left({\color{gray}2.79 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$10.7 \mathrm{ms} \pm 71.4 \mathrm{μs}\left({\color{gray}-1.610 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$10.7 \mathrm{ms} \pm 74.3 \mathrm{μs}\left({\color{gray}0.735 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$10.8 \mathrm{ms} \pm 75.9 \mathrm{μs}\left({\color{gray}-2.733 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$10.8 \mathrm{ms} \pm 73.0 \mathrm{μs}\left({\color{gray}-0.045 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$10.7 \mathrm{ms} \pm 82.6 \mathrm{μs}\left({\color{gray}-0.717 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$10.9 \mathrm{ms} \pm 90.9 \mathrm{μs}\left({\color{gray}1.18 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$10.7 \mathrm{ms} \pm 70.9 \mathrm{μs}\left({\color{gray}-0.004 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$10.8 \mathrm{ms} \pm 77.7 \mathrm{μs}\left({\color{gray}-0.401 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$10.7 \mathrm{ms} \pm 62.3 \mathrm{μs}\left({\color{gray}-0.103 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.01 \mathrm{ms} \pm 45.4 \mathrm{μs}\left({\color{gray}-0.206 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$57.2 \mathrm{ms} \pm 341 \mathrm{μs}\left({\color{gray}1.93 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$109 \mathrm{ms} \pm 675 \mathrm{μs}\left({\color{gray}-0.984 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$63.1 \mathrm{ms} \pm 450 \mathrm{μs}\left({\color{gray}0.963 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$72.2 \mathrm{ms} \pm 629 \mathrm{μs}\left({\color{gray}0.353 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$80.7 \mathrm{ms} \pm 617 \mathrm{μs}\left({\color{gray}0.179 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$87.7 \mathrm{ms} \pm 531 \mathrm{μs}\left({\color{gray}0.889 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$45.6 \mathrm{ms} \pm 325 \mathrm{μs}\left({\color{gray}-1.604 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$73.0 \mathrm{ms} \pm 598 \mathrm{μs}\left({\color{gray}0.502 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$51.4 \mathrm{ms} \pm 408 \mathrm{μs}\left({\color{gray}0.583 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$60.0 \mathrm{ms} \pm 564 \mathrm{μs}\left({\color{gray}1.50 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$61.9 \mathrm{ms} \pm 433 \mathrm{μs}\left({\color{gray}0.458 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$61.6 \mathrm{ms} \pm 410 \mathrm{μs}\left({\color{gray}-0.009 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$122 \mathrm{ms} \pm 660 \mathrm{μs}\left({\color{red}12.0 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$133 \mathrm{ms} \pm 697 \mathrm{μs}\left({\color{red}8.85 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$23.7 \mathrm{ms} \pm 187 \mathrm{μs}\left({\color{gray}2.87 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$524 \mathrm{ms} \pm 1.52 \mathrm{ms}\left({\color{gray}-0.132 \mathrm{\%}}\right) $$ Flame Graph

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

Labels

area/apps area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

4 participants