Skip to content

perf(core): reduce public render query count for menu resolution and page metadata paths #1189

Description

@ahliweb

Summary

Public menu-heavy routes still show a relatively high query count on render even after downstream template duplication is removed.

The most obvious hotspot is packages/core/src/menus/index.ts, where menu item URLs are resolved per item via resolveContentUrl() / resolveTaxonomyUrl().

Context

This was observed while validating AWCMS-Micro against upstream EmDash.

Downstream-only cleanup has already been done:

  • removed incorrect public links that used id instead of slug
  • enabled locale-prefixed downstream routing workarounds where needed
  • added public link prefetching
  • parallelized homepage collection fetches
  • removed duplicate homepage menu renders
  • removed duplicate footer widget usage on non-detail public pages

Those changes improved correctness and reduced some duplicate downstream work, but they did not materially remove the homepage query-count ceiling.

Evidence

Representative observations from live validation after downstream cleanup:

  • / commonly reports db.count=23
  • /id commonly reports db.count=23
  • /posts commonly reports db.count=13
  • /news commonly reports db.count=13
  • /about commonly reports db.count=4

The remaining gap strongly suggests a core-owned menu/runtime path rather than a downstream template issue.

Suspected Cause

Current menu flow appears to be:

  1. getMenu() fetches the menu row
  2. it fetches menu items
  3. it fetches collection URL patterns
  4. buildMenuTree() resolves each item individually
  5. resolveMenuItem() calls resolveContentUrl() / resolveTaxonomyUrl() per item

This means menu-heavy pages can still pay effectively per-item lookup cost, including locale fallback lookups.

Proposed Fix Direction

1. Batch-resolve content references per collection

  • collect all referenced content groups by collection first
  • fetch requested-locale rows in one query per collection
  • fetch fallback rows for unresolved groups in one follow-up query per collection
  • build an in-memory lookup map
  • make per-item resolution read from the map rather than query again

2. Batch-resolve taxonomy references

  • collect referenced taxonomy groups first
  • resolve requested-locale rows in one query
  • resolve fallback rows for misses in one follow-up query
  • build an in-memory taxonomy lookup map

3. Re-profile metadata/fragment collection afterward

EmDashHead.astro already parallelizes site settings, plugin metadata, and fragments, so the menu path looks like the clearest first target.

Acceptance Criteria

  • fewer queries on menu-heavy public routes
  • no regression in locale-aware menu URLs
  • no regression in translation fallback behavior
  • no regression for custom URLs, collection items, or taxonomy items
  • request-cache behavior remains intact

Suggested Validation

  1. Add/update a test around getMenu() with multiple page/post/taxonomy references across locales.
  2. Measure query count before/after on a menu-heavy public route.
  3. Confirm locale-specific rows are preferred and deterministic fallback still works when a translation is missing.

Related Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions