Performance Benchmarks for Open-SEO: Lighthouse Scoring and Thresholds Explained
Open-SEO evaluates web page performance using Lighthouse scores normalized to a 0-100 scale alongside hard-coded thresholds—such as a 1.5-second Time-to-First-Byte limit—to flag optimization opportunities.
The every-app/open-seo repository is a Cloudflare-based SEO auditing platform that leverages the Lighthouse engine to generate actionable performance metrics. Understanding the performance benchmarks for open-seo requires examining how raw Lighthouse data is transformed into stored scores and how specific timing thresholds trigger audit warnings.
Lighthouse Score Normalization and Categories
Open-SEO does not store raw Lighthouse decimals. Instead, src/server/lib/dataforseoLighthousePayload.ts converts the Lighthouse categories.performance?.score (a 0-1 float) into a percentage using scoreToPercent, producing the 0-100 scale used throughout the application【/src/server/lib/dataforseoLighthousePayload.ts†L12-L15】.
The available audit categories are defined in src/shared/lighthouse.ts, which explicitly lists "performance" as a primary category driving the benchmark calculations【/src/shared/lighthouse.ts†L2-L4】.
Hard-Coded Timing Thresholds
Beyond numeric scores, the platform enforces strict timing benchmarks. In src/shared/audit-issues.ts, Open-SEO flags a slow Time-to-First-Byte (TTFB) when the HTML response exceeds 1.5 seconds (1500 ms), generating the warning: "The HTML response took over 1.5 seconds. Slow time-to-first-byte drags down every downstream performance metric"【/src/shared/audit-issues.ts†L207-L209】.
Data Storage and Schema
Performance scores are persisted using the schema defined in src/server/lib/lighthouseStoredPayload.ts. The field is defined as z.number().nullable(), allowing the database to store integer scores (0-100) or null when Lighthouse fails to complete【/src/server/lib/lighthouseStoredPayload.ts†L70-L71】.
Client-Side Filtering Logic
The audit results UI implements benchmark filtering in src/client/features/audit/results/AuditResultsTableFilterLogic.ts. This logic handles null performance scores by excluding them from numeric comparisons and supports range-based filtering via minPerf and maxPerf parameters. The code checks row.performanceScore == null and applies matchesRange(row.performanceScore, filters.minPerf, filters.maxPerf) to enforce user-defined thresholds【/src/client/features/audit/results/AuditResultsTableFilterLogic.ts†L12-L14】.
Interpreting Performance Scores in Practice
When analyzing results, consider the following benchmark tiers:
- 90-100 (Excellent): Indicates optimal Core Web Vitals and loading performance.
- 70-89 (Good): Acceptable performance with minor optimization opportunities.
- 0-69 (Needs Work): Signals significant speed issues requiring immediate attention.
Any TTFB measurement exceeding the 1.5-second threshold automatically triggers a warning regardless of the overall Lighthouse score, as this metric directly impacts every downstream performance indicator.
Code Examples: Working with Performance Benchmarks
The following snippets demonstrate how to retrieve benchmarks, check thresholds, and filter results programmatically:
// 1️⃣ Retrieve a page’s Lighthouse performance score (0‑100)
import { getAuditById } from '@/server/lib/audit';
const audit = await getAuditById(auditId);
const perfScore = audit.performanceScore; // e.g., 84
// 2️⃣ Detect a slow TTFB (threshold > 1.5 s)
if (audit.timing?.ttfb && audit.timing.ttfb > 1500) {
console.warn('Slow TTFB – exceeds 1.5 s benchmark');
}
// 3️⃣ UI filter: only show pages with performance ≥ 80
const filtered = audits.filter(a =>
a.performanceScore != null && a.performanceScore >= 80
);
Summary
- Lighthouse Conversion: Raw 0-1 scores are converted to a 0-100 scale in
src/server/lib/dataforseoLighthousePayload.ts. - TTFB Threshold: A hard limit of 1.5 seconds is enforced in
src/shared/audit-issues.ts. - Storage: Scores are stored as nullable integers via
src/server/lib/lighthouseStoredPayload.ts. - Filtering: The UI respects null values and supports min/max range filters as implemented in
src/client/features/audit/results/AuditResultsTableFilterLogic.ts.
Frequently Asked Questions
What is the minimum passing performance score in Open-SEO?
While Open-SEO does not enforce a strict "passing" gate, industry standards applied within the platform consider scores below 70 as requiring immediate optimization. The UI filtering logic allows users to set custom minimum thresholds (e.g., 80 or 90) to match their specific quality benchmarks.
How does Open-SEO handle pages that fail to generate a Lighthouse score?
Pages that fail to run Lighthouse are stored with a null performance score according to the schema in src/server/lib/lighthouseStoredPayload.ts. The filtering logic in src/client/features/audit/results/AuditResultsTableFilterLogic.ts explicitly checks for row.performanceScore == null and excludes these rows from numeric range filters to prevent data pollution.
Why is the Time-to-First-Byte threshold set at 1.5 seconds?
The 1.5-second TTFB limit defined in src/shared/audit-issues.ts aligns with industry best practices for server response times. Exceeding this threshold indicates backend latency that inevitably degrades subsequent metrics like First Contentful Paint and Largest Contentful Paint, making it a reliable early warning signal for infrastructure issues.
Where is the performance benchmark data stored in the Open-SEO database?
Performance scores are persisted in the database according to the lighthouseStoredPayload schema found in src/server/lib/lighthouseStoredPayload.ts. This schema defines the performance field as z.number().nullable(), ensuring compatibility with the 0-100 integer scale while accommodating failed audits with null values.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →