# How the Open SEO Audit Limits System Prevents Excessive Resource Consumption

> Discover how the Open SEO audit limits system prevents excessive resource consumption. It enforces tier-based caps on page counts and capacity units, validating requests before crawling begins.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: internals
- Published: 2026-07-31

---

**The Open SEO audit limits system prevents excessive resource consumption by enforcing tier-based caps on page counts and capacity units, validating every request against hard limits before any crawling or Lighthouse analysis begins.**

The `every-app/open-seo` repository implements a robust safeguard mechanism to protect server resources from runaway audit processes. By defining strict boundaries in [`src/shared/audit-limits.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/audit-limits.ts) and enforcing them through the `AuditService`, the system ensures that free and paid tiers operate within predictable compute budgets. This layered validation strategy intercepts oversized requests before they can impact infrastructure.

## Tier-Based Configuration and Hard Limits

### Centralized Limit Definitions in [`src/shared/audit-limits.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/audit-limits.ts)

The foundation of the protection layer rests on three exported constants that establish absolute boundaries for any audit:

- `MIN_AUDIT_PAGES = 10` ensures audits have a minimum viable scope.
- `FREE_MAX_AUDIT_PAGES = 50` caps free-tier users to prevent abuse.
- `PAID_MAX_AUDIT_PAGES = 10_000` provides a generous but bounded ceiling for paid accounts.

These values serve as the **single source of truth** used by both the frontend validation and the backend enforcement logic.

### The `AUDIT_LIMITS` Tier Configuration

Located in [`src/server/features/audit/services/audit-capacity.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/audit/services/audit-capacity.ts), the `AUDIT_LIMITS` record maps each subscription tier to its specific resource budget:

```typescript
const AUDIT_LIMITS = {
  free: {
    maxPagesPerAudit: FREE_MAX_AUDIT_PAGES, // 50
    maxCapacityUnits: 2000,
    maxRunningAudits: 1
  },
  paid: {
    maxPagesPerAudit: PAID_MAX_AUDIT_PAGES, // 10_000
    maxCapacityUnits: 100000,
    maxRunningAudits: Infinity
  }
};

```

**Capacity units** represent a composite metric combining page crawls and Lighthouse analysis operations, ensuring that compute-heavy audits are accounted for beyond simple page counts.

## Runtime Enforcement and Capacity Estimation

### Input Sanitization with `clampAuditMaxPages`

Before any capacity calculation, user input is sanitized using the `clampAuditMaxPages` utility. This function constrains requested page counts to the inclusive range `[MIN_AUDIT_PAGES, tierMax]`, preventing negative values or excessive requests from reaching the processing pipeline.

```typescript
import { clampAuditMaxPages } from "@/server/features/audit/services/audit-capacity";

const userMaxPages = 200;               // User asks for 200 pages
const safeMaxPages = clampAuditMaxPages(userMaxPages);
// safeMaxPages will be 50 for a free tier (FREE_MAX_AUDIT_PAGES)

```

### Pre-Flight Capacity Calculation

The `getEstimatedAuditCapacity` function computes the total resource weight of an audit by aggregating page count and anticipated Lighthouse checks.

```typescript
import { getEstimatedAuditCapacity } from "@/server/features/audit/services/audit-capacity";

const estimate = getEstimatedAuditCapacity({
  maxPages: 30,
  lighthouseStrategy: "auto",   // auto = mobile + desktop checks on sampled pages
});
// estimate => { pagesTotal: 30, lighthouseTotal: 20, total: 50 }

```

### Service-Level Validation in [`AuditService.ts`](https://github.com/every-app/open-seo/blob/main/AuditService.ts)

The `AuditService` orchestrates the enforcement layer. When receiving a new audit request, it retrieves the caller's tier, applies clamping, calculates capacity, and validates against the budget:

```typescript
import { AUDIT_LIMITS } from "@/server/features/audit/services/audit-capacity";

function validateAuditRequest(limitTier: "free" | "paid", maxPages?: number) {
  const limits = AUDIT_LIMITS[limitTier];
  const pages = clampAuditMaxPages(maxPages);
  
  if (pages > limits.maxPagesPerAudit) {
    throw new Error(
      `Audit exceeds ${limitTier} tier page limit of ${limits.maxPagesPerAudit}`
    );
  }
  
  // Further capacity checks compare against limits.maxCapacityUnits …
}

```

This validation occurs before any network requests to the target domain or Lighthouse workers are initialized.

## Fail-Fast Architecture for Resource Protection

By executing all limit checks during the request validation phase—**before** spawning crawl workers or launching browser instances—the system implements a fail-fast pattern. Rejected audits return immediate validation errors with clear messaging (e.g., "Free plan audits are limited to 50 pages") sourced from [`src/client/lib/error-messages.ts`](https://github.com/every-app/open-seo/blob/main/src/client/lib/error-messages.ts), eliminating wasted compute cycles, bandwidth, and storage that would otherwise be consumed by invalid operations.

## Summary

- **Hard limits** in [`src/shared/audit-limits.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/audit-limits.ts) define absolute page boundaries (10–10,000) based on tier.
- The **`AUDIT_LIMITS`** configuration in [`audit-capacity.ts`](https://github.com/every-app/open-seo/blob/main/audit-capacity.ts) extends page caps to composite **capacity units** and concurrent audit limits.
- **`clampAuditMaxPages`** and **`getEstimatedAuditCapacity`** sanitize inputs and calculate resource costs before execution.
- **[`AuditService.ts`](https://github.com/every-app/open-seo/blob/main/AuditService.ts)** enforces tier budgets at the API boundary, rejecting oversized requests before expensive crawling begins.
- This layered approach ensures the Open SEO platform remains stable and responsive regardless of user input variations.

## Frequently Asked Questions

### What happens if a user requests more pages than their tier allows?

The `clampAuditMaxPages` function automatically reduces the request to the tier maximum (e.g., 50 for free plans). If the resulting capacity estimate still exceeds `maxCapacityUnits`, the `AuditService` returns a validation error before the crawl starts, preventing any resource consumption.

### How are capacity units calculated for an audit?

Capacity units combine the total page count with Lighthouse analysis operations. The `getEstimatedAuditCapacity` helper in [`src/server/features/audit/services/audit-capacity.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/audit/services/audit-capacity.ts) calculates this by summing `pagesTotal` and `lighthouseTotal`, where Lighthouse counts vary by strategy (mobile, desktop, or both).

### Where are the audit limit constants defined in the codebase?

Absolute numeric boundaries reside in **[`src/shared/audit-limits.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/audit-limits.ts)** (e.g., `FREE_MAX_AUDIT_PAGES`), while tier-specific configurations including capacity budgets are defined in **[`src/server/features/audit/services/audit-capacity.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/audit/services/audit-capacity.ts)**.

### Why does the system check limits before starting the crawl?

Performing validation during the request phase—rather than mid-crawl—implements a **fail-fast** design that protects compute resources. This ensures that CPU, memory, and bandwidth are never allocated to audits that violate tier constraints, maintaining platform stability for all users.