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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions