Aller au contenu

Performance Optimization

This guide explains how to optimize performance in the Plus261 platform.

Performance optimization is crucial for providing a good user experience. This guide covers optimization techniques for both API and Web components.

Only request fields you need:

# ✅ Good - Only requested fields
query {
products {
id
name
}
}
# ❌ Bad - Requesting all fields
query {
products {
id
name
description
price
category {
id
name
description
}
}
}

Always paginate large result sets:

query {
products(paging: { limit: 20, offset: 0 }) {
id
name
}
}

Filter at the database level:

query {
products(filter: { status: { eq: "ACTIVE" } }) {
id
name
}
}

Use DataLoaders for relations:

// ✅ Good - Uses DataLoader
@Relation('category', () => Category)
category: Category;
// DataLoader batches requests

Add indexes for frequently queried fields:

// In schema definition
export const products = pgTable(
'products',
{
id: uuid('id').primaryKey(),
status: varchar('status'),
organizationId: uuid('organization_id'),
},
(table) => [
index('products_status_idx').on(table.status),
index('products_org_id_idx').on(table.organizationId),
],
);
// ✅ Good - Uses index
const products = await db.select().from(products).where(eq(products.status, 'ACTIVE'));
// ❌ Bad - Full table scan
const allProducts = await db.select().from(products);
const active = allProducts.filter((p) => p.status === 'ACTIVE');

Use database aggregations instead of processing in code:

// ✅ Good - Database aggregation
const result = await db
.select({
total: sum(products.price),
count: count(),
})
.from(products);
// ❌ Bad - Processing in code
const all = await db.select().from(products);
const total = all.reduce((sum, p) => sum + p.price, 0);

Cache frequently accessed data:

import { cache } from '../cache';
async function getProducts() {
const cacheKey = 'products:active';
const cached = await cache.get(cacheKey);
if (cached) {
return cached;
}
const products = await db.select().from(products);
await cache.set(cacheKey, products, 300); // 5 minutes
return products;
}

Set appropriate cache headers:

response.headers.set('Cache-Control', 'public, max-age=300');

Split code to reduce initial load:

// Lazy load components
const HeavyComponent = lazy(() => import('./HeavyComponent.svelte'));
// Use optimized images
<img src="/images/product.jpg?w=400&h=300&format=webp" alt="Product" />

For long lists:

<script>
import { VirtualList } from '@components/VirtualList';
let items = $state([...]);
</script>
<VirtualList items={items} itemHeight={50}>
{#each visibleItems as item}
<ProductCard {item} />
{/each}
</VirtualList>

Memoize expensive computations:

<script>
import { memo } from 'svelte';
let products = $state([...]);
const expensiveComputation = memo(() => {
return products.map(p => {
// Expensive operation
return computeValue(p);
});
});
</script>

Monitor key metrics:

  • Response Time - API response times
  • Throughput - Requests per second
  • Error Rate - Percentage of errors
  • Database Query Time - Slow query detection

Profile code to find bottlenecks:

import { performance } from 'perf_hooks';
const start = performance.now();
// Your code
const end = performance.now();
console.log(`Execution time: ${end - start}ms`);

Log operations that take too long:

const SLOW_QUERY_THRESHOLD = 1000; // 1 second
const start = Date.now();
const result = await db.query(...);
const duration = Date.now() - start;
if (duration > SLOW_QUERY_THRESHOLD) {
logger.warn('Slow query detected', {
duration,
query: query.toString(),
});
}

Don’t optimize prematurely. Measure first:

// Profile before optimizing
const profile = await profileFunction(expensiveFunction);
console.log('Profile:', profile);

Focus on code that runs frequently:

  • API endpoints with high traffic
  • Database queries in loops
  • Frequently rendered components
// ✅ Good - O(1) lookup
const map = new Map(users.map((u) => [u.id, u]));
const user = map.get(userId);
// ❌ Bad - O(n) lookup
const user = users.find((u) => u.id === userId);

Batch multiple operations:

// ✅ Good - Single query
const users = await db.select().from(users).where(inArray(users.id, userIds));
// ❌ Bad - Multiple queries
const users = await Promise.all(
userIds.map((id) => db.select().from(users).where(eq(users.id, id))),
);

Load resources on demand:

// Lazy load heavy modules
const heavyModule = await import('./heavy-module');

When optimizing, check:

  • Are queries using indexes?
  • Are results paginated?
  • Are N+1 queries avoided?
  • Is caching used appropriately?
  • Are images optimized?
  • Is code split appropriately?
  • Are expensive operations memoized?
  • Are metrics monitored?