---
title: "Performance"
description: "Integrator guide — React 19 cache(), client bootstrap single-flight, PostgreSQL pool SSOT, and provider enforcement."
locale: "en"
---
# Performance Optimization

Profiling and optimization strategies for Ring Platform integrators. For operator-facing overview, see [Performance patterns](/docs/features/performance.md). For production infrastructure, see [Deployment performance](/docs/deployment/performance.md).

> **Info**
> Use **Founder** / **Developer** tabs in the docs sidebar to filter this page.

> **Warning**
> Ring Platform does **not** use client-side Firestore. Firebase is Admin SDK only via `lib/firebase-admin.server.ts`. Client Firebase code is limited to `public/firebase-messaging-sw.js` for FCM.

### For founders

## What affects load times

| Factor | Effect |
|--------|--------|
| Server Components default | Most routes ship zero client JS for pure rendering |
| Request dedup (`cache()`) | One Firestore read per document per server render |
| Cached store catalog | Product list shared across API route and server action |
| Batched Web Vitals | One analytics POST per page load instead of five |
| Provider SSOT | Single credit-balance stream, single tunnel connection |
| Build-time Firebase mock | Static pages build without live credentials |

### For developers

## Caching layers (mirror of features doc)

| Layer | Scope | SSOT |
|-------|-------|------|
| React `cache()` | Per-request server | `lib/services/firebase-service-manager.ts` |
| `'use cache'` + `cacheTag` | Cross-request server | `features/store/config.ts` → `getCachedProductCatalog()` |
| EntityCache 30s TTL | Server process | `lib/database/DatabaseService.ts` |
| Vendor status single-flight | Client tab | `hooks/use-vendor-status.ts` (30s TTL) |
| Credit bootstrap single-flight | Client tab | `hooks/use-credit-balance.ts` (5s TTL, `userId`-keyed) |
| Web Vitals batch | Client tab | `components/providers/web-vitals-provider.tsx` (1.5s debounce) |
| Session refetch | Client tab | `features/auth/components/session-provider.tsx` (`15 * 60`, no focus/offline) |

Full operator narrative: [Performance patterns](/docs/features/performance.md).

## React 19 `cache()` in Server Components

```typescript
import { getCachedDocument, getCachedCollection } from '@/lib/services/firebase-service-manager'

// Multiple calls during one render → one Firestore read
const entity = await getCachedDocument('entities', 'abc123')
const same = await getCachedDocument('entities', 'abc123') // cache hit
```

Cache scope is the current Server Component render pass only. For cross-request caching, use Next 16 Cache Components (`'use cache'`) or `revalidate` exports.

## Build-time Firebase mocking

During `next build`, `lib/firebase/build-mock.server.ts` detects `NEXT_PHASE=phase-production-build` and returns mock Firestore/Auth instances. Chainable `where()` / `orderBy()` / `limit()` return empty result sets — no credentials required for SSG.

## DatabaseService query optimization

```typescript
import { db } from '@/lib/database'

const result = await db().queryDocs({
  collection: 'entities',
  filters: [{ field: 'status', operator: '==', value: 'active' }],
  orderBy: [{ field: 'createdAt', direction: 'desc' }],
  pagination: { limit: 20, offset: 0 },
})

if (!result.success) throw result.error ?? new Error('Query failed')
```

- Prefer `findDocById` over filtering by `id` in `queryDocs`.
- Use `filters` + `pagination` at the database layer — do not fetch-all-then-filter in application code.
- EntityCache provides 30s read-after-write consistency on `entities` — no manual cache for basic cases.

> **Warning**
> Do not call `db.users.findById()` or similar. The API is `db().findDocById('users', id)` or `db().queryDocs({ collection, filters, … })`.

## PostgreSQL pool SSOT

```typescript
import { getSharedPgPool } from '@/lib/database'

// PostGIS / raw SQL only — not for routine CRUD
const pool = await getSharedPgPool()
```

`getSharedPgPool()` in `lib/database/shared-pg-pool.ts` returns the connected adapter pool after `initializeDatabase()`. **`new Pool(` must appear only under `lib/database/`** — enforced by gate 7 of `scripts/validate-provider-ssot.sh`.

Routine persistence: `db().createDoc` / `findDocById` / `queryDocs` / `transaction`.

## Provider SSOT enforcement

Before merging hook or provider changes:

```bash
./scripts/validate-provider-ssot.sh
```

Seven gates — full table in [Best practices](/docs/development/best-practices.md#provider-ssot-script). Key paths:

- `SessionProvider` → `features/auth/components/session-provider.tsx` (duplicates under `components/providers/` deleted)
- `useVendorStatus` → sole owner of `fetch('/api/vendor/status')`
- `useCreditBalance` → sole owner of `'/api/wallet/credit/balance'` string in TS/TSX

## Server Components by default

Pages in `app/` are Server Components unless marked `'use client'`. Client boundaries belong on interactive leaves: checkout forms, maps, wallet UIs, admin dashboards.

## Rendering strategy exports

```typescript
export const revalidate = 60        // ISR — revalidate every 60s
export const dynamic = 'force-dynamic'  // user-specific, no cache
```

## Web Vitals collection

`WebVitalsProvider` batches Core Web Vitals into one debounced `POST /api/analytics/web-vitals`. There is **no** per-metric POST from `useReportWebVitals` directly — do not document or implement five separate analytics calls per page load.

For build analysis:

```bash
npm run build
npm run analyze
```

Firebase cache metrics (`getCacheMetrics()`) are dev-only when `FIREBASE_DEBUG_LOGS=true`.

## Related documentation

  
- **[Performance patterns (features)](/docs/features/performance.md)** — Operator + developer caching table and server/client SSOT.

  
- **[Best practices](/docs/development/best-practices.md)** — db() rules, platform_settings, SSOT script gates.

  
- **[Code structure](/docs/development/code-structure.md)** — Provider matrix and P4 hook consolidation.

  
- **[Deployment performance](/docs/deployment/performance.md)** — Production monitoring and infrastructure tuning.
