Performance Optimization Guide
This guide provides comprehensive strategies for optimizing Plugged.in performance, scalability, and resource utilization across different deployment scenarios.System Requirements
Minimum Requirements
| Component | Minimum | Recommended | Enterprise |
|---|---|---|---|
| CPU | 2 cores | 4 cores | 8+ cores |
| RAM | 4 GB | 8 GB | 16+ GB |
| Storage | 20 GB SSD | 50 GB SSD | 100+ GB SSD |
| Network | 100 Mbps | 1 Gbps | 10+ Gbps |
Database Requirements
Copy
# PostgreSQL Configuration
shared_buffers = 256MB # 25% of RAM
effective_cache_size = 1GB # 50% of RAM
work_mem = 4MB # Per operation
maintenance_work_mem = 64MB # For maintenance
wal_buffers = 16MB # WAL buffer
checkpoint_segments = 32 # Checkpoint frequency
Application Optimization
Memory Management
Node.js Optimization
Copy
# Memory Settings
NODE_OPTIONS="--max-old-space-size=4096 --optimize-for-size --enable-gc-interval=30000"
# Garbage Collection
GC_INTERVAL=30000
GC_THRESHOLD=0.8
MEMORY_MAX_BUFFER=1GB
MEMORY_MAX_RSS=1.5GB
Application-Level Caching
Copy
# Caching Strategy
CACHE_TYPE=redis
CACHE_TTL=3600
CACHE_MAX_SIZE=100MB
CACHE_REDIS_URL=redis://localhost:6379
# Memory Cache (Fallback)
MEMORY_CACHE_ENABLED=true
MEMORY_CACHE_TTL=300
MEMORY_CACHE_MAX_SIZE=50MB
Database Optimization
Query Optimization
Copy
# Query Performance
DB_QUERY_TIMEOUT=30000
DB_CONNECTION_TIMEOUT=5000
DB_STATEMENT_TIMEOUT=60000
DB_SLOW_QUERY_LOG=true
DB_SLOW_QUERY_THRESHOLD=1000
# Connection Pooling
DB_POOL_MIN=2
DB_POOL_MAX=20
DB_POOL_IDLE_TIMEOUT=30000
DB_POOL_ACQUIRE_TIMEOUT=60000
Index Optimization
Copy
-- Essential Indexes for Performance
CREATE INDEX CONCURRENTLY idx_servers_profile_uuid ON servers(profile_uuid);
CREATE INDEX CONCURRENTLY idx_documents_profile_uuid ON documents(profile_uuid);
CREATE INDEX CONCURRENTLY idx_documents_created_at ON documents(created_at DESC);
CREATE INDEX CONCURRENTLY idx_collections_profile_uuid ON collections(profile_uuid);
CREATE INDEX CONCURRENTLY idx_notifications_user_id ON notifications(user_id);
CREATE INDEX CONCURRENTLY idx_notifications_unread ON notifications(unread) WHERE unread = true;
-- Composite Indexes for Common Queries
CREATE INDEX CONCURRENTLY idx_servers_profile_transport ON servers(profile_uuid, transport);
CREATE INDEX CONCURRENTLY idx_documents_profile_source ON documents(profile_uuid, source, created_at DESC);
Frontend Optimization
Bundle Optimization
Copy
# Build Optimization
BUNDLE_ANALYZER=true
SOURCEMAP=false
MINIFY=true
COMPRESS=true
# Code Splitting
LAZY_LOAD_ROUTES=true
TREE_SHAKING=true
DEAD_CODE_ELIMINATION=true
Runtime Performance
Copy
// React Optimization
const MemoizedComponent = React.memo(MyComponent);
const CallbackRef = useCallback(() => {}, []);
const MemoValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
// Virtual Scrolling for Large Lists
import { FixedSizeList as List } from 'react-window';
Infrastructure Optimization
Docker Optimization
Multi-Stage Builds
Copy
# Dockerfile optimization
FROM node:18-alpine AS base
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN npm ci --only=production
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 12005
CMD ["node", "server.js"]
Docker Compose Optimization
Copy
version: '3.8'
services:
pluggedin-app:
image: pluggedin/app:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 1G
environment:
- NODE_OPTIONS=--max-old-space-size=1536
volumes:
- ./uploads:/app/uploads:ro
restart: unless-stopped
pluggedin-mcp:
image: pluggedin/mcp:latest
deploy:
resources:
limits:
cpus: '0.5'
memory: 1G
environment:
- MCP_SERVER_MEMORY=512M
restart: unless-stopped
Kubernetes Optimization
Resource Management
Copy
apiVersion: apps/v1
kind: Deployment
metadata:
name: pluggedin-app
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
containers:
- name: pluggedin-app
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 12005
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /api/health
port: 12005
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
Horizontal Pod Autoscaling
Copy
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: pluggedin-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: pluggedin-app
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 120
policies:
- type: Percent
value: 50
periodSeconds: 60
Database Performance
PostgreSQL Tuning
Configuration Optimization
Copy
# Memory Settings
shared_buffers = 1GB # 25% of system RAM
effective_cache_size = 3GB # 75% of system RAM
work_mem = 16MB # Per operation memory
maintenance_work_mem = 256MB # For maintenance operations
wal_buffers = 64MB # WAL writing buffer
# Checkpoint Settings
checkpoint_segments = 128 # Increase for high write loads
checkpoint_timeout = 15min # Checkpoint frequency
checkpoint_completion_target = 0.9 # Spread checkpoint I/O
# Query Planning
default_statistics_target = 1000 # More detailed statistics
random_page_cost = 1.5 # SSD optimization
effective_io_concurrency = 200 # SSD concurrent requests
# Logging
log_min_duration_statement = 1000ms # Slow query logging
log_checkpoints = on # Checkpoint logging
log_connections = on # Connection logging
log_disconnections = on # Disconnection logging
Regular Maintenance
Copy
# Daily Maintenance
vacuum (analyze, verbose) pluggedin_db;
# Weekly Maintenance
reindex concurrently (verbose) pluggedin_db;
# Monthly Maintenance
vacuum full analyze verbose pluggedin_db;
# Monitor long-running queries
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';
Connection Pooling
PgBouncer Configuration
Copy
# /etc/pgbouncer/pgbouncer.ini
[databases]
pluggedin_db = host=localhost port=5432 dbname=pluggedin_db
[pgbouncer]
pool_mode = transaction
listen_port = 6432
listen_addr = *
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
# Pool Settings
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 5
# Timeouts
server_reset_query = DISCARD ALL
server_check_delay = 30
server_check_query = select 1
server_lifetime = 3600
server_idle_timeout = 600
# Performance
pkt_buf = 4096
max_packet_size = 2147483647
Caching Strategies
Redis Configuration
Performance Tuning
Copy
# /etc/redis/redis.conf
# Memory Management
maxmemory 2GB
maxmemory-policy allkeys-lru
maxmemory-samples 5
# Performance
tcp-keepalive 300
timeout 300
tcp-keepalive 60
# Persistence (if needed)
save 900 1
save 300 10
save 60 10000
# Advanced
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
Cache Warming
Copy
# Warm up frequently accessed data
redis-cli MGET user:profile:1 user:profile:2 user:profile:3
# Preload popular MCP servers
redis-cli SMEMBERS trending:servers
# Warm up document search index
redis-cli KEYS "doc:search:*" | head -100 | xargs redis-cli MGET
Application-Level Caching
Implementation Strategies
Copy
// Cache Manager Implementation
class CacheManager {
private cache = new Map();
private maxSize = 1000;
private ttl = 3600000; // 1 hour
set(key: string, value: any, ttl?: number) {
if (this.cache.size >= this.maxSize) {
this.evictLRU();
}
this.cache.set(key, {
value,
expiry: Date.now() + (ttl || this.ttl)
});
}
get(key: string) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expiry) {
this.cache.delete(key);
return null;
}
return item.value;
}
private evictLRU() {
// Remove oldest entry
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
}
Monitoring & Alerting
Key Metrics to Monitor
Application Metrics
Copy
# Response Times
curl -w "@curl-format.txt" -o /dev/null -s "https://plugged.in/api/health"
# Concurrent Connections
ss -tuln | grep :12005 | wc -l
# Memory Usage
ps aux | grep pluggedin | grep -v grep | awk '{sum+=$6} END {print sum/1024 "MB"}'
Database Metrics
Copy
-- Connection Count
SELECT count(*) FROM pg_stat_activity WHERE datname = 'pluggedin_db';
-- Table Sizes
SELECT schemaname, tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Index Usage
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
Performance Benchmarks
Load Testing
Copy
# Using Apache Bench
ab -n 1000 -c 10 https://plugged.in/api/health
# Using Artillery
artillery quick --count 100 -n 20 https://plugged.in/api/search
# Using k6
k6 run --vus 10 --duration 30s load-test.js
Benchmark Scripts
Copy
// load-test.js for k6
import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 200 },
{ duration: '5m', target: 200 },
{ duration: '2m', target: 0 },
],
};
export default function () {
let response = http.get('https://plugged.in/api/search?q=test');
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Scalability Strategies
Horizontal Scaling
Load Balancer Configuration
Copy
# nginx.conf
upstream pluggedin_app {
least_conn;
server app1:12005 max_fails=3 fail_timeout=30s;
server app2:12005 max_fails=3 fail_timeout=30s;
server app3:12005 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name plugged.in;
location / {
proxy_pass http://pluggedin_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
# Buffering
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
Database Scaling
Read Replica Setup
Copy
# docker-compose with read replicas
services:
db-primary:
image: postgres:15
environment:
- POSTGRES_DB=pluggedin_db
- POSTGRES_USER=pluggedin
- POSTGRES_PASSWORD=password
volumes:
- postgres_primary:/var/lib/postgresql/data
command: postgres -c wal_level=replica
db-replica:
image: postgres:15
environment:
- POSTGRES_DB=pluggedin_db
- POSTGRES_USER=pluggedin_ro
- POSTGRES_PASSWORD=password
volumes:
- postgres_replica:/var/lib/postgresql/data
command: postgres -c hot_standby=on
depends_on:
- db-primary
Troubleshooting Performance Issues
Common Performance Problems
High Memory Usage
Diagnosis:Copy
# Check process memory
pm2 monit
# Check system memory
free -h
# Check for memory leaks
node -e "setInterval(() => { console.log(process.memoryUsage()) }, 1000)"
Copy
# Restart services
pm2 restart all
# Clear caches
redis-cli FLUSHALL
# Check for memory leaks in logs
journalctl -u pluggedin-app -f | grep -i memory
Slow Database Queries
Diagnosis:Copy
-- Find slow queries
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
-- Check table statistics
SELECT schemaname, tablename, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
Copy
# Update statistics
ANALYZE VERBOSE pluggedin_db;
# Rebuild indexes
REINDEX INDEX CONCURRENTLY idx_servers_profile_uuid;
# Check for missing indexes
pg_stat_user_indexes
High CPU Usage
Diagnosis:Copy
# Check CPU usage
top -p $(pgrep -f pluggedin)
# Check CPU per process
ps aux | grep pluggedin | grep -v grep
# Check system load
uptime
Copy
# Enable slow query logging
echo "log_min_duration_statement = 1000" >> postgresql.conf
# Check for expensive operations
EXPLAIN ANALYZE SELECT * FROM documents WHERE profile_uuid = 'uuid' ORDER BY created_at DESC;
Performance Best Practices
Development Phase
-
Code Optimization
Copy
# Use performance monitoring npm install --save-dev @next/bundle-analyzer # Enable source maps for debugging SOURCEMAP=true npm run build # Use tree shaking npm run build -- --analyze -
Database Design
Copy
-- Use appropriate data types ALTER TABLE users ALTER COLUMN created_at TYPE TIMESTAMP; -- Add constraints for performance ALTER TABLE documents ADD CONSTRAINT check_source CHECK (source IN ('upload', 'ai_generated', 'api')); -- Use partitioning for large tables CREATE TABLE documents_y2024 PARTITION OF documents FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
Production Optimization
-
Resource Allocation
Copy
# Set appropriate limits ulimit -n 65536 ulimit -u 4096 # Monitor resource usage iotop -p $(pgrep -f pluggedin) -
Regular Maintenance
Copy
# Daily cleanup find /app/uploads -type f -mtime +30 -delete # Weekly optimization pnpm db:optimize # Monthly analysis pnpm performance:analyze

