---
title: Performance
sort: 140
section-id: guides
keywords: performance, code splitting, lazy loading, caching, optimisation, Core Web Vitals
description: Performance optimisation strategies for Velox apps — code splitting, lazy loading, and caching
language: en
---
# Performance

Velox is designed to be fast by default. The Rust-based compiler handles tree-shaking, code splitting, and asset optimisation automatically. This guide covers the additional strategies you can apply to push your application to peak performance.
## Core Web Vitals Targets
Before optimising, establish baselines. Aim for:
| Metric | Good | Needs Work |
|--------|------|-----------|
| LCP (Largest Contentful Paint) | ≤ 2.5s | > 4.0s |
| FID / INP (Interaction to Next Paint) | ≤ 200ms | > 500ms |
| CLS (Cumulative Layout Shift) | ≤ 0.1 | > 0.25 |
| TTFB (Time to First Byte) | ≤ 800ms | > 1800ms |
Use Velox's built-in analytics to monitor these in production:
```typescript
// velox.config.ts
export default defineConfig({
analytics: {
webVitals: true,
endpoint: '/api/analytics/vitals',
},
});
```
## Code Splitting
Velox automatically splits your JavaScript bundle by route. Every route gets its own chunk, and shared code is extracted into a common chunk. You do not need to configure this.
For further control, use dynamic imports:
```typescript
// Only loads when the user clicks "Open"
const HeavyEditor = lazy(() => import('./HeavyEditor'));
function PostPage() {
const isEditing = signal(false);
return (
{post.title}
{isEditing.value && (
}>
)}
);
}
```
## Lazy Hydration
Delay hydration of interactive components until they are needed:
```tsx
```
The less JavaScript you ship to the client, the better the INP score.
## Image Optimisation
Enable image optimisation in `velox.config.ts`:
```typescript
assets: {
imageOptimisation: {
enabled: true,
formats: ['webp', 'avif'],
quality: 85,
maxWidth: 2000,
},
},
```
Use the `` component for automatic width/height and format negotiation:
```tsx
import { Image } from 'velox';
```
The `priority` prop adds a `` tag to the document head and marks the image as `fetchpriority="high"`, which is the single biggest LCP improvement for image-heavy pages.
## HTTP Caching
Set appropriate `Cache-Control` headers for your routes:
```typescript
// In a route server block
response.headers.set('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');
// Or via config for specific paths
export default defineConfig({
headers: [
{
source: '/assets/*',
headers: [
{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
],
},
{
source: '/',
headers: [
{ key: 'Cache-Control', value: 'public, max-age=0, s-maxage=3600, stale-while-revalidate=86400' },
],
},
],
});
```
## Server-Side Caching
Cache expensive computations and database queries:
```typescript
import { useCache } from 'velox/server';
const cache = useCache();
async function getPopularPosts() {
const cached = await cache.get('posts:popular');
if (cached) return cached;
const posts = await db.posts.findMany({
where: { published: true },
orderBy: { viewCount: 'desc' },
take: 10,
});
await cache.set('posts:popular', posts, { ttl: 300 }); // 5 minutes
return posts;
}
```
## Database Query Optimisation
Common patterns that prevent N+1 queries:
```typescript
// Bad: N+1 query
const posts = await db.post.findMany();
const postsWithAuthors = await Promise.all(
posts.map(p => db.user.findById(p.authorId)) // N extra queries!
);
// Good: single query with include
const postsWithAuthors = await db.post.findMany({
include: { author: { select: { id: true, name: true } } },
});
```
Add indexes for commonly filtered columns:
```sql
-- In a migration
CREATE INDEX CONCURRENTLY idx_posts_published_created
ON posts (published, created_at DESC)
WHERE published = true;
```
## Edge Deployment
Deploy to edge locations close to your users:
```typescript
// velox.config.ts
export default defineConfig({
build: {
target: 'edge',
},
});
```
Edge-compatible routes must use Web APIs only:
```typescript
// ✅ Edge-compatible
import { defineHandler } from 'velox/server';
export const GET = defineHandler(async (req) => {
const data = await fetch('https://api.example.com/data');
return Response.json(await data.json());
});
// ❌ Not edge-compatible (uses Node.js built-ins)
import fs from 'node:fs';
```
## Bundle Analysis
Generate and review a bundle analysis report:
```bash
ANALYZE=1 npm run build
# Opens .velox/output/analyze.html in your browser
```
Look for:
- Unexpectedly large dependencies (replace with smaller alternatives)
- Duplicate dependencies at different versions
- Client-side imports of server-only packages
## Prefetching
Configure link prefetching globally:
```typescript
export default defineConfig({
prefetch: {
defaultStrategy: 'hover', // 'hover' | 'viewport' | false
concurrency: 2, // max concurrent prefetch requests
ignore: ['/admin/*', '/api/*'],
},
});
```
## Font Loading
Avoid layout shift from font loading:
```css
/* styles/global.css */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-weight: 100 900;
font-display: swap; /* show fallback text immediately */
}
```
```tsx
// layouts/default.velox
```
## Performance Monitoring
Integrate with monitoring services:
```typescript
// lib/monitoring.ts
export function reportWebVitals({ name, value, id }: Metric) {
fetch('/api/analytics/vitals', {
method: 'POST',
body: JSON.stringify({ name, value, id, page: window.location.pathname }),
keepalive: true,
});
}
```