Skip to content

Latest commit

 

History

History
91 lines (71 loc) · 4.08 KB

File metadata and controls

91 lines (71 loc) · 4.08 KB

Performance Optimization Checklist

Performance posture for the NimbusOps showcase, ordered by where the wins actually are: page output first, WordPress runtime second, database last (most expensive to change).

Sample measured numbers live in ../artifacts/lighthouse-report.md.


1. Why this stack is already fast

  • No synchronous third-party call on the request path. The form endpoint persists + schedules; the n8n network hop happens out-of-band. The visitor's POST returns as soon as the row is written.
  • Append-only leads table with three indexes (email, created_at, sync_status), the admin viewer and re-sync queries hit indexes, never a full scan.
  • No options bloat. Only two small autoload options (nimbusops_leads_schema_version, tag map). Schema version is an int; the tag map is tiny. Nothing large is autoloaded.
  • Rate limiter uses transients, which become object-cache reads on a Redis-backed install, no DB round-trip on the hot path when caching is on.

2. Page output (Core Web Vitals)

Target Action Where
LCP Hero image on single Solution uses fetchpriority="high" + eager load single-solution.php
LCP/CLS Grid/card images loading="lazy" below the fold shortcodes.php, child CSS
CLS Form inputs have explicit box model; no late-injected layout child style.css
INP Form JS is a single delegated submit listener, no per-field handlers shortcodes.php
Render Child CSS enqueued after parent with filemtime cache-buster child functions.php

3. Caching strategy

  • Page cache: LiteSpeed Cache (or your host's FastCGI cache). Exclude nothing special, the form posts via REST, which is never cached.
  • REST endpoint: POST /nimbusops/v1/lead is inherently uncacheable; do not let an over-eager cache plugin cache wp-json GETs that include nonces.
  • Object cache: Redis (Till Krüss drop-in) makes the transient rate-limiter and FluentCRM lookups memory-fast. Strongly recommended in production.
  • Fragment: the solutions grid is a candidate for a short transient if the catalog is large and rarely changes:
// Illustrative, wrap the WP_Query in shortcodes.php if the grid gets heavy.
$html = get_transient( 'nimbusops_solutions_grid' );
if ( false === $html ) {
    $html = build_grid();
    set_transient( 'nimbusops_solutions_grid', $html, HOUR_IN_SECONDS );
}

4. Database

  • The leads table is the only custom table. Indexes are defined at creation (dbDelta in form-logger.php). No LIKE '%...%' queries anywhere.
  • The admin viewer is capped at 100 rows (ORDER BY created_at DESC LIMIT 100), hits the created_at index, bounded result set.
  • Re-sync queries filter on sync_status (indexed). Even with millions of leads the "find unsynced" query stays index-bound.
  • If lead volume grows past ~1M rows, add a composite (sync_status, created_at) index and partition the admin view by date.

5. Asset discipline

  • Zero front-end JS dependency: the form runtime is a single inline script via an empty-src handle (wp_add_inline_script). No jQuery, no bundle.
  • CSS is design-token driven and ~4KB; inline it as critical CSS on the landing template if you chase a perfect LCP.

6. i18n / a11y note

Every user-facing string is wrapped in __() / esc_html__() from day one, and the child theme ships load_child_theme_textdomain + an RTL-ready stylesheet (logical properties, no hard-coded left/right in flow). i18n and a11y are cheap at first commit and expensive to retrofit, see the form's aria-live status region and :focus-visible outlines.

7. Verification

# Lighthouse CI on the landing + a single Solution page
lighthouse https://nimbusops.local/ --output=json --output-path=artifacts/home.json
lighthouse https://nimbusops.local/solutions/automation/ --output=json --output-path=artifacts/solution.json

# Query Monitor: confirm no slow queries on the form submit + single Solution view
# Redis: redis-cli INFO stats | grep keyspace_hits  (hit ratio should climb)