---
title: "Паттерни Оптимізації Продуктивності"
description: "Кешування бази даних, дедуплікація React cache(), патерни Firebase Admin SDK та оптимізація Server Components для Ring Platform."
locale: "uk"
---
# Паттерни Оптимізації Продуктивності

Ring Platform використовує **React 19 `cache()`** для дедуплікації даних у Server Components, **шар абстракції бази даних** (`DatabaseService` + адаптери) для роботи з PostgreSQL або Firestore, та **Firebase Admin SDK** (`firebase-service-manager.ts`) для кешованих читаннь Firestore у режимі `firebase-full`.

> **Info**
> Усі приклади коду нижче посилаються на **реальні файли** кодової бази — `lib/services/firebase-service-manager.ts`, `lib/database/DatabaseService.ts`, `lib/database/adapters/FirebaseAdapter.ts`. Вигадані утиліти (session-storage кеші, кастомний RingApiClient, віртуалізація) не є частиною Ring Platform.

## React 19 Server Components та отримання даних

### Пряме отримання даних у Server Components (рекомендовано)

{`// Сервіси використовують DatabaseService (PostgreSQL або Firebase адаптер)
import { getEntities } from '@/features/entities/services/entity-service'

export default async function EntitiesPage() {
  const entities = await getEntities()
  return 
}`}

Уникайте викликів власних HTTP API з Server Components — App Router Server Components можуть імпортувати сервіси безпосередньо без round-trip запиту.

### React 19 `cache()` для дедуплікації запитів

React 19 `cache()` дедуплікує ідентичні одночасні виклики в межах одного запиту. Ring Platform використовує це у двох місцях:

**1. `firebase-service-manager.ts`** — кешовані читання Firestore (Admin SDK, тільки режим `firebase-full`):

{`import { cache } from 'react'
import { getAdminDb } from '../firebase-admin.server'

export const getCachedDocument = cache(async (
  collection: string,
  docId: string
): Promise => {
  const db = getAdminDb()
  const docRef = db.collection(collection).doc(docId)
  const doc = await docRef.get()
  return doc.exists ? doc : null
})`}

**2. `DatabaseService`** — кеш сутностей для консистентності read-after-write (TTL 30 секунд):

{`class EntityCache {
  private cache = new Map<string, { data: any; timestamp: number }>()
  private readonly TTL = 30000 // 30 секунд

  set(key: string, data: any) {
    this.cache.set(key, { data, timestamp: monotime() })
  }

  get(key: string) {
    const entry = this.cache.get(key)
    if (entry && (monotime() - entry.timestamp) < this.TTL) return entry.data
    this.cache.delete(key)
    return null
  }

  invalidate(key: string) { this.cache.delete(key) }
}`}

### Хуки React 19

{`'use client'
import { useActionState } from 'react'

export function CreateEntityForm() {
  const [state, formAction, isPending] = useActionState(
    createEntityAction,
    { success: false, errors: [] }
  )

  return (
    
      
      {isPending && Створення...}
      {state.errors.length > 0 && (
        {state.errors.map(e => {e})}
      )}
      
        {isPending ? 'Створення...' : 'Створити сутність'}
      
    
  )
}`}

## Шар абстракції бази даних

### Контракт `DatabaseService`

Реальний `DatabaseService` маршрутизує через `BackendSelector` до `PostgreSQLAdapter` або `FirebaseAdapter`. Його API запитів використовує **один об'єктний параметр**:

{`// Реальний API — один об'єктний параметр
const result = await db.query({
  collection: 'entities',
  filters: [{ field: 'status', operator: 'eq', value: 'active' }],
  orderBy: [{ field: 'createdAt', direction: 'desc' }],
  pagination: { limit: 20, offset: 0 }
})
// result: { success: boolean; data: DbRow[]; error?: Error }

// Один документ
const doc = await db.findById('users', userId)
// doc: { success: boolean; data: T | null; error?: Error }

// Мутації
await db.create('entities', data)
await db.update('entities', id, partial)
await db.delete('entities', id)

// Транзакції
await db.transaction(async (txn) => {
  await txn.create('orders', orderData)
  await txn.update('inventory', productId, { stock: newStock })
})`}

### FirebaseAdapter (Admin SDK — тільки серверна частина)

**Реальний** `FirebaseAdapter` використовує `firebase-admin/firestore`, а не клієнтський Firebase SDK:

{`import { Firestore, FieldValue, Timestamp } from 'firebase-admin/firestore'
import { cert, getApps, initializeApp } from 'firebase-admin/app'

export class FirebaseAdapter implements IDatabaseService {
  private firestore: Firestore | null = null

  async findById(collection: string, id: string): Promise<DatabaseResult> {
    if (!this.firestore) await this.connect()
    const doc = await this.firestore.collection(collection).doc(id).get()
    if (!doc.exists) {
      return { success: true, data: undefined as any }
    }
    return { success: true, data: { id: doc.id, ...doc.data() } as T }
  }

  async query(query: DatabaseQuery): Promise<DatabaseResult<T[]>> {
    // query = { collection, filters?, orderBy?, pagination? }
    // Використовує Admin SDK Query builder
    let q: FirebaseFirestore.Query = this.firestore.collection(query.collection)
    // ... фільтр, сортування, пагінація, виконання
    const snapshot = await q.get()
    return {
      success: true,
      data: snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })) as T[]
    }
  }
}`}

**Ключова відмінність:** Приклад у попередній версії документації показував клієнтський `getFirestore()` з `firebase/firestore` — це неправильно для серверного адаптера платформи. Реальний адаптер використовує виключно `firebase-admin/firestore`.

## Стратегія кешування

| Рівень | Область | Механізм | Розташування |
|--------|---------|----------|--------------|
| React `cache()` | На запит | Дедуплікація React 19 | `firebase-service-manager.ts` (Firebase) / Server Components |
| EntityCache | TTL 30 с | In-memory Map | `DatabaseService.ts` |
| HTTP/CDN | Рівень сторінки | Next.js `stale-while-revalidate` | `next.config.mjs` заголовки |

**Кешування `sessionStorage`** на сервері не використовується. Кешування на стороні браузера залишається стандартним Web API патернам (не є частиною цієї кодової бази).

## Оптимізація Firebase (FirebaseAdmin SDK)

### Пакетні операції

`firebase-service-manager.ts` надає:

{`import { createBatchWriter, executeBatch } from '@/lib/services/firebase-service-manager'

const batch = createBatchWriter()
const ref1 = db.collection('entities').doc('id1')
batch.update(ref1, { status: 'archived' })
const ref2 = db.collection('entities').doc('id2')
batch.update(ref2, { status: 'archived' })
await executeBatch(batch)`}

Для ліміту пакетів Firestore у 500 елементів та вимог до складових індексів див. [документацію Firestore](https://firebase.google.com/docs/firestore/query-data/indexing).

### Відстеження метрик (тільки для налагодження)

`firebase-service-manager.ts` включає опціональні метрики для розробки (контролюються `FIREBASE_DEBUG_LOGS=true`):

{`// lib/services/firebase-service-manager.ts — метрики налагодження
const metrics = {
  cacheHits: 0,
  cacheMisses: 0,
  totalRequests: 0,
  getHitRate(): number {
    return this.totalRequests > 0 ? (this.cacheHits / this.totalRequests) * 100 : 0
  },
}

export function getCacheMetrics() {
  return {
    hitRate: metrics.getHitRate(),
    totalRequests: metrics.totalRequests,
    cacheHits: metrics.cacheHits,
    cacheMisses: metrics.cacheMisses
  }
}`}

Це інструмент для розробки/налагодження — **не система моніторингу продакшну**. Він логує в `console.log`, а не в зовнішній сервіс. Бюджет продуктивності в `next.config.mjs` не налаштовано.

## Оптимізація збірки

### Поточний `next.config.mjs`

{`const nextConfig = {
  reactStrictMode: true,
  cacheComponents: true,
  // Повний файл див. для env, redirects, headers, i18n конфігурації
}`}

**Відсутні `swcMinify`, `experimental.optimizeCss` та `performance`** — це функції Next.js 12/13. Next.js 16 керує SWC мініфікацією та оптимізацією CSS автоматично.

## Підсумок

- **Реальне кешування**: React 19 `cache()` для дедуплікації запитів, EntityCache для 30-секундної консистентності read-after-write
- **Реальний Firebase адаптер**: `firebase-admin/firestore` (Admin SDK), ніколи не клієнтський `firebase/firestore`
- **Реальний контракт `DatabaseService`**: `findById`, `query({collection, filters, orderBy, pagination})`, `transaction`
- **Видалено вигадані патерни**: `SessionStorageCache`, `RingApiClient`, маршрутизація `DB_HYBRID_MODE`, `next.config` бюджети продуктивності, фейкові KPI ("95% зниження", "17.0s", "55KB"), `trackWebVitals`, віртуалізація
- **Бенчмарки продуктивності** не відстежуються в цій кодовій базі — результати профілювання належать до CI дашбордів, а не документації
