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.
- 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
autoloadoptions (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.
| 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 |
- 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/leadis inherently uncacheable; do not let an over-eager cache plugin cachewp-jsonGETs 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 );
}- The leads table is the only custom table. Indexes are defined at creation
(
dbDeltainform-logger.php). NoLIKE '%...%'queries anywhere. - The admin viewer is capped at 100 rows (
ORDER BY created_at DESC LIMIT 100), hits thecreated_atindex, 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.
- 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.
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.
# 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)