[{"content":"Authentication between microservices is one of those things that seems simple until you actually try to implement it.\nWe went through 4 different patterns over 18 months. Each one solved some problems but created new ones. Here\u0026rsquo;s what we learned, and what we eventually settled on.\nThe problem You have 15 microservices. API Gateway authenticates users with JWT. But how do internal services verify requests from each other?\nService A needs to call Service B. Service B needs to know:\nIs this request from a legitimate service? Which user is this on behalf of? What permissions does this service/user have? Seems straightforward. It\u0026rsquo;s not.\nPattern 1: Shared JWT secret (Don\u0026rsquo;t do this) Our first approach: just pass the user\u0026rsquo;s JWT between services.\n// API Gateway app.post(\u0026#39;/api/orders\u0026#39;, authenticateUser, async (req, res) =\u0026gt; { const token = req.headers.authorization; // Pass token to order service const order = await axios.post(\u0026#39;http://order-service/orders\u0026#39;, { userId: req.user.id, items: req.body.items }, { headers: { Authorization: token } }); res.json(order.data); }); // Order Service app.post(\u0026#39;/orders\u0026#39;, verifyJWT, async (req, res) =\u0026gt; { // Same JWT verification as gateway const order = await createOrder(req.user.id, req.body.items); res.json(order); }); Why we thought it would work:\nSimple Only one JWT secret to manage User context flows naturally Why it failed:\nEvery service needs the JWT secret - security nightmare No service identity - can\u0026rsquo;t tell if caller is Gateway or random service Token expiration - user\u0026rsquo;s token expires mid-request chain Permission confusion - user permissions ≠ service permissions Lasted 2 months before we abandoned it.\nPattern 2: Service-to-service API keys Next attempt: each service has an API key.\n// Order Service const SERVICE_KEYS = { \u0026#39;gateway\u0026#39;: \u0026#39;sk_gateway_abc123\u0026#39;, \u0026#39;payment\u0026#39;: \u0026#39;sk_payment_xyz789\u0026#39;, \u0026#39;notification\u0026#39;: \u0026#39;sk_notif_def456\u0026#39; }; function authenticateService(req, res, next) { const apiKey = req.headers[\u0026#39;x-api-key\u0026#39;]; const service = Object.keys(SERVICE_KEYS).find( name =\u0026gt; SERVICE_KEYS[name] === apiKey ); if (!service) { return res.status(401).json({ error: \u0026#39;Invalid API key\u0026#39; }); } req.service = service; next(); } app.post(\u0026#39;/orders\u0026#39;, authenticateService, async (req, res) =\u0026gt; { // req.service tells us who called // req.body.userId tells us on behalf of whom const order = await createOrder(req.body.userId, req.body.items); res.json(order); }); Better than JWT:\nServices have identity Keys don\u0026rsquo;t expire Can revoke specific service\u0026rsquo;s access Still had problems:\nKey management hell - 15 services × 14 potential callers = 210 key pairs Key rotation - how do you rotate without downtime? No user context - have to pass userId separately Still just strings in config - easy to leak Lasted 4 months. Key rotation broke prod twice.\nPattern 3: Mutual TLS (mTLS) Heard about mTLS from a conference talk. Sounded perfect.\nEach service gets a certificate. Services verify each other\u0026rsquo;s certs.\n# docker-compose.yml excerpt order-service: volumes: - ./certs/order-service.crt:/certs/service.crt - ./certs/order-service.key:/certs/service.key - ./certs/ca.crt:/certs/ca.crt // Order Service const https = require(\u0026#39;https\u0026#39;); const fs = require(\u0026#39;fs\u0026#39;); const options = { cert: fs.readFileSync(\u0026#39;/certs/service.crt\u0026#39;), key: fs.readFileSync(\u0026#39;/certs/service.key\u0026#39;), ca: fs.readFileSync(\u0026#39;/certs/ca.crt\u0026#39;), requestCert: true, rejectUnauthorized: true }; https.createServer(options, app).listen(443, () =\u0026gt; { console.log(\u0026#39;Secure server running\u0026#39;); }); // Verify calling service function checkServiceAuth(req, res, next) { const cert = req.socket.getPeerCertificate(); if (!cert || !cert.subject) { return res.status(401).json({ error: \u0026#39;No client certificate\u0026#39; }); } req.callingService = cert.subject.CN; next(); } Pros:\nActually secure No shared secrets Built into TLS protocol Industry standard Cons:\nCertificate management is hard Renewal automation is painful Debugging connection issues is hell Need service mesh (Istio/Linkerd) to make it bearable We tried running our own CA. Don\u0026rsquo;t do that. Use a service mesh or don\u0026rsquo;t use mTLS.\nLasted 6 months until we migrated to Kubernetes with Istio.\nPattern 4: JWTs with service mesh (What we use now) Current setup: Istio handles mTLS between services. We use JWTs for identity and permissions.\nBut not user JWTs. Service JWTs.\n// JWT payload for service-to-service calls { \u0026#34;iss\u0026#34;: \u0026#34;auth-service\u0026#34;, \u0026#34;sub\u0026#34;: \u0026#34;service:order-service\u0026#34;, \u0026#34;aud\u0026#34;: \u0026#34;service:payment-service\u0026#34;, \u0026#34;iat\u0026#34;: 1706745600, \u0026#34;exp\u0026#34;: 1706745900, // 5 minutes \u0026#34;scope\u0026#34;: \u0026#34;order:create payment:charge\u0026#34;, \u0026#34;user_id\u0026#34;: \u0026#34;user_123\u0026#34;, // Original user context \u0026#34;user_roles\u0026#34;: [\u0026#34;customer\u0026#34;], \u0026#34;trace_id\u0026#34;: \u0026#34;abc-123\u0026#34; // For logging } How it works:\nAPI Gateway authenticates user with user JWT Gateway generates service JWT for downstream calls Services verify service JWT, not user JWT User context flows as claims, not as auth Code:\n// Shared auth library const jwt = require(\u0026#39;jsonwebtoken\u0026#39;); const SERVICE_KEY = process.env.SERVICE_JWT_SECRET; function createServiceToken(opts) { return jwt.sign({ sub: `service:${process.env.SERVICE_NAME}`, aud: `service:${opts.targetService}`, scope: opts.scope, user_id: opts.userId, user_roles: opts.userRoles, trace_id: opts.traceId }, SERVICE_KEY, { expiresIn: \u0026#39;5m\u0026#39;, issuer: \u0026#39;auth-service\u0026#39; }); } function verifyServiceToken(token) { return jwt.verify(token, SERVICE_KEY, { audience: `service:${process.env.SERVICE_NAME}`, issuer: \u0026#39;auth-service\u0026#39; }); } // API Gateway app.post(\u0026#39;/api/orders\u0026#39;, authenticateUser, async (req, res) =\u0026gt; { // Create service token for order service const serviceToken = createServiceToken({ targetService: \u0026#39;order-service\u0026#39;, scope: \u0026#39;order:create\u0026#39;, userId: req.user.id, userRoles: req.user.roles, traceId: req.id }); const response = await axios.post(\u0026#39;http://order-service/orders\u0026#39;, { items: req.body.items }, { headers: { \u0026#39;Authorization\u0026#39;: `Bearer ${serviceToken}`, \u0026#39;X-Trace-Id\u0026#39;: req.id } }); res.json(response.data); }); // Order Service app.post(\u0026#39;/orders\u0026#39;, verifyServiceAuth, async (req, res) =\u0026gt; { // req.service contains verified service token claims // req.service.user_id is the original user // req.service.scope contains permissions if (!req.service.scope.includes(\u0026#39;order:create\u0026#39;)) { return res.status(403).json({ error: \u0026#39;Insufficient permissions\u0026#39; }); } const order = await createOrder(req.service.user_id, req.body.items); // Need to call payment service const paymentToken = createServiceToken({ targetService: \u0026#39;payment-service\u0026#39;, scope: \u0026#39;payment:charge\u0026#39;, userId: req.service.user_id, userRoles: req.service.user_roles, traceId: req.service.trace_id }); await chargePayment(order, paymentToken); res.json(order); }); Why this works 1. Service identity Each JWT specifies caller (sub) and target (aud). Services can verify who\u0026rsquo;s calling.\n2. Short-lived tokens 5-minute expiration. Even if leaked, quickly becomes useless.\n3. Scoped permissions Each call specifies what it can do. Principle of least privilege.\n4. User context preserved user_id and user_roles flow through the call chain for authorization and auditing.\n5. Single secret One SERVICE_JWT_SECRET shared between all internal services. Easier than 210 API keys.\n6. mTLS for transport Istio handles TLS between services. JWT handles authorization.\nImplementation tips 1. Separate user auth from service auth Don\u0026rsquo;t use user JWTs for service-to-service calls. Generate new tokens.\n2. Short expiration times 5 minutes max. Most calls complete in seconds.\n3. Include trace IDs Helps debug request flows across services.\n{ \u0026#34;trace_id\u0026#34;: \u0026#34;abc-123\u0026#34;, \u0026#34;span_id\u0026#34;: \u0026#34;def-456\u0026#34; } 4. Scope permissions explicitly Don\u0026rsquo;t give services blanket access. Specify exactly what each call can do.\n// Bad scope: \u0026#34;admin\u0026#34; // Good scope: \u0026#34;order:create payment:charge\u0026#34; 5. Log everything function verifyServiceAuth(req, res, next) { try { const token = extractToken(req); const claims = verifyServiceToken(token); logger.info(\u0026#39;Service call authenticated\u0026#39;, { caller: claims.sub, target: claims.aud, user: claims.user_id, scope: claims.scope, trace_id: claims.trace_id }); req.service = claims; next(); } catch (err) { logger.warn(\u0026#39;Service auth failed\u0026#39;, { error: err.message, token: token.substring(0, 20) }); res.status(401).json({ error: \u0026#39;Unauthorized\u0026#39; }); } } What about the secret? Yeah, all services need SERVICE_JWT_SECRET. Still a shared secret.\nBut:\nIt\u0026rsquo;s internal only (never leaves cluster) Only signs service tokens (not user tokens) Easier to rotate (all services restart with new secret) Istio mTLS protects it in transit We rotate it monthly with zero downtime:\nDeploy all services with both old and new secrets Services accept tokens signed with either After 5 minutes (max token lifetime), all tokens use new secret Remove old secret Other patterns we considered Service mesh only (no JWT)\nIstio mTLS verifies service identity. But doesn\u0026rsquo;t help with user context or permissions.\nOAuth2 client credentials\nOvercomplicated for internal services. Adds auth server dependency.\nSigned requests (AWS SigV4)\nSign each request with service credentials. Works but complex to implement.\nLessons learned Don\u0026rsquo;t use user auth for service auth - Different security models Service mesh + JWT is powerful - Mesh for transport, JWT for authorization Keep tokens short-lived - 5 minutes is plenty Log service call patterns - Helps debug and audit Start simple - You can always add complexity later We\u0026rsquo;re happy with this setup. Been running 8 months with zero auth-related incidents.\nThe key insight: services are not users. They need different authentication, different permissions, different token lifetimes.\nTreat them differently and life gets easier.\n","permalink":"https://pixcave.com/posts/microservices-auth-patterns/","summary":"\u003cp\u003eAuthentication between microservices is one of those things that seems simple until you actually try to implement it.\u003c/p\u003e\n\u003cp\u003eWe went through 4 different patterns over 18 months. Each one solved some problems but created new ones. Here\u0026rsquo;s what we learned, and what we eventually settled on.\u003c/p\u003e\n\u003ch2 id=\"the-problem\"\u003eThe problem\u003c/h2\u003e\n\u003cp\u003eYou have 15 microservices. API Gateway authenticates users with JWT. But how do internal services verify requests from each other?\u003c/p\u003e\n\u003cp\u003eService A needs to call Service B. Service B needs to know:\u003c/p\u003e","title":"Microservices Auth: We Tried 4 Patterns, Here's What Actually Worked"},{"content":"Incident Report: Node.js Memory Leak Analysis Date: 2026-01-20\nSeverity: P1 (Production Impact)\nMTTR: 14 days\nRoot Cause: Event listener leak in WebSocket handler\nTimeline of Events Day 1 - Jan 6, 09:30 UTC\nMonitoring alerts: API instances restarting every 6 hours Memory usage shows sawtooth pattern (gradual climb, sudden drop) Initial hypothesis: Database connection leak Day 3 - Jan 8\nRuled out database connections (pool metrics normal) Added heap profiling to staging environment Identified EventEmitter instances growing unbounded Day 7 - Jan 13\nNarrowed down to WebSocket message handlers Still unable to identify exact leak source Memory profiling shows 50K+ listener registrations Day 14 - Jan 20, 14:15 UTC\nRoot cause identified: Missing removeListener() in disconnect handler Fix deployed: 14:45 UTC Memory usage stabilized within 2 hours Technical Analysis Memory Leak Pattern Heap Memory Usage Over 6 Hours ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 512MB ┤ ╱╱╱╱╱ [restart] │ ╱╱ │ ╱╱ 256MB ┤ ╱╱ │ ╱╱ 128MB ┤ ╱╱ │ ╱╱ 64MB ┤ ╱╱ └───────────────────────────── 0h 2h 4h 6h Characteristics:\nLinear growth: ~13MB/hour No garbage collection effectiveness Crash at 512MB (container limit) Restart triggers temporary relief Diagnostic Process Step 1: Heap Snapshot Analysis\n// Capture heap snapshots programmatically const v8 = require(\u0026#39;v8\u0026#39;); const fs = require(\u0026#39;fs\u0026#39;); function captureHeapSnapshot() { const filename = `heap-${Date.now()}.heapsnapshot`; const snapshot = v8.writeHeapSnapshot(filename); console.log(`Snapshot written to ${snapshot}`); } // Capture every 30 minutes setInterval(captureHeapSnapshot, 30 * 60 * 1000); Snapshot Comparison Results:\nObject Type Snapshot 1 (2h) Snapshot 2 (4h) Growth EventEmitter 1,250 2,480 +98% Function 3,100 6,210 +100% Array 8,420 17,100 +103% Finding: EventEmitter instances doubling every 2 hours\nStep 2: Event Listener Tracking\n// Instrument EventEmitter to track listener additions const EventEmitter = require(\u0026#39;events\u0026#39;); const originalOn = EventEmitter.prototype.on; EventEmitter.prototype.on = function(event, listener) { console.log(`[LISTENER ADD] ${event} on ${this.constructor.name}`); console.trace(); return originalOn.call(this, event, listener); }; Output Analysis:\n[LISTENER ADD] message on WebSocketHandler at WebSocketHandler.handleConnection (ws-handler.js:45) at WebSocketServer.emit (events.js:310) ... [Count after 1 hour]: 8,432 \u0026#39;message\u0026#39; listeners [Count after 2 hours]: 16,891 \u0026#39;message\u0026#39; listeners Conclusion: Listeners never removed on connection close\nStep 3: Root Cause Identification\nProblematic Code:\nclass WebSocketHandler { handleConnection(socket) { const messageHandler = (data) =\u0026gt; { this.processMessage(data, socket); }; // ❌ Problem: Listener added socket.on(\u0026#39;message\u0026#39;, messageHandler); socket.on(\u0026#39;close\u0026#39;, () =\u0026gt; { // ❌ Problem: Listener NOT removed console.log(\u0026#39;Socket closed\u0026#39;); // Missing: socket.removeListener(\u0026#39;message\u0026#39;, messageHandler); }); } processMessage(data, socket) { // Process message logic } } Issue: Each new connection registers a message listener but never removes it on disconnect. With 50K connections/day, memory grows unbounded.\nSolution Implemented Fix Applied:\nclass WebSocketHandler { handleConnection(socket) { const messageHandler = (data) =\u0026gt; { this.processMessage(data, socket); }; socket.on(\u0026#39;message\u0026#39;, messageHandler); socket.on(\u0026#39;close\u0026#39;, () =\u0026gt; { // ✅ Fixed: Explicitly remove listener socket.removeListener(\u0026#39;message\u0026#39;, messageHandler); console.log(\u0026#39;Socket closed, listener removed\u0026#39;); }); } processMessage(data, socket) { // Process message logic } } Alternative Solutions Considered:\nUsing once() instead of on() - Not applicable (need persistent listener) Automatic cleanup with WeakMap - Complex, potential edge cases Connection pooling with max limits - Doesn\u0026rsquo;t address root cause Verification Results Memory Usage After Fix:\nHeap Memory Usage (Stable) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 512MB ┤ │ │ 256MB ┤ │ ════════════════════════ [stable ~128MB] 128MB ┤ │ 64MB ┤ └───────────────────────────── 0h 12h 24h 48h 72h Metrics Comparison:\nMetric Before Fix After Fix Improvement Memory baseline 64MB → 512MB (growth) 128MB (stable) 75% reduction Restart frequency Every 6 hours None (72h+) 100% Active listeners 50K+ (growing) ~150 (stable) 99.7% Connection capacity Limited Unlimited N/A Diagnostic Tools \u0026amp; Techniques Tool 1: Node.js Built-in Profiler # Start with heap profiling enabled node --inspect --heap-prof server.js # Connect Chrome DevTools chrome://inspect Best For: Initial investigation, visual heap analysis\nTool 2: clinic.js # Install npm install -g clinic # Profile with Doctor (identifies event loop issues) clinic doctor -- node server.js # Profile with HeapProfiler clinic heapprofiler -- node server.js Output: Generates detailed reports showing memory allocation hotspots\nTool 3: memwatch-next const memwatch = require(\u0026#39;@airbnb/node-memwatch-next\u0026#39;); memwatch.on(\u0026#39;leak\u0026#39;, (info) =\u0026gt; { console.error(\u0026#39;Memory leak detected:\u0026#39;); console.error(info); }); memwatch.on(\u0026#39;stats\u0026#39;, (stats) =\u0026gt; { console.log(\u0026#39;GC stats:\u0026#39;, { num_full_gc: stats.num_full_gc, num_inc_gc: stats.num_inc_gc, heap_compactions: stats.heap_compactions, estimated_base: stats.estimated_base, current_base: stats.current_base, min: stats.min, max: stats.max }); }); Best For: Production monitoring, early leak detection\nTool 4: Heap Diff Analysis const memwatch = require(\u0026#39;@airbnb/node-memwatch-next\u0026#39;); let hd; memwatch.on(\u0026#39;stats\u0026#39;, () =\u0026gt; { if (!hd) { hd = new memwatch.HeapDiff(); } else { const diff = hd.end(); console.log(\u0026#39;Heap diff:\u0026#39;); console.log(JSON.stringify(diff, null, 2)); hd = null; } }); Reveals: Objects growing between GC cycles\nPrevention Strategies Strategy 1: Automated Listener Audit // audit-listeners.js const EventEmitter = require(\u0026#39;events\u0026#39;); function auditListeners(emitter, maxListeners = 10) { const events = emitter.eventNames(); events.forEach(event =\u0026gt; { const count = emitter.listenerCount(event); if (count \u0026gt; maxListeners) { console.warn(`[LEAK WARNING] ${event}: ${count} listeners`); console.warn(\u0026#39;Stack trace:\u0026#39;, new Error().stack); } }); } // Run audit every 5 minutes setInterval(() =\u0026gt; { auditListeners(myEventEmitter); }, 5 * 60 * 1000); Strategy 2: Connection Registry class ConnectionManager { constructor() { this.connections = new Set(); } register(socket) { const handler = (data) =\u0026gt; this.handleMessage(data, socket); socket.on(\u0026#39;message\u0026#39;, handler); socket.on(\u0026#39;close\u0026#39;, () =\u0026gt; { socket.removeListener(\u0026#39;message\u0026#39;, handler); this.connections.delete(socket); }); this.connections.add(socket); } handleMessage(data, socket) { // Handle message } // Diagnostic method getConnectionCount() { return this.connections.size; } } Strategy 3: Memory Monitoring Alerts // monitoring.js const v8 = require(\u0026#39;v8\u0026#39;); function checkMemoryUsage() { const heapStats = v8.getHeapStatistics(); const usedHeap = heapStats.used_heap_size; const totalHeap = heapStats.heap_size_limit; const usagePercent = (usedHeap / totalHeap) * 100; if (usagePercent \u0026gt; 80) { console.error(\u0026#39;[CRITICAL] Memory usage at\u0026#39;, usagePercent.toFixed(2), \u0026#39;%\u0026#39;); // Trigger alert to monitoring system sendAlert({ severity: \u0026#39;critical\u0026#39;, message: `High memory usage: ${usagePercent}%`, metrics: heapStats }); } } setInterval(checkMemoryUsage, 60 * 1000); // Check every minute Lessons Learned Event listeners are not garbage collected until explicitly removed\nUse removeListener() or off() in cleanup code Consider using once() for single-use listeners Heap snapshots are invaluable for leak diagnosis\nTake snapshots at regular intervals Compare snapshots to identify growing objects Focus on objects with high retention count Monitoring should include listener counts\nTrack EventEmitter.listenerCount() for critical emitters Alert on unusual growth patterns Implement max listener limits Automated testing can catch leaks early\nWrite tests that simulate high connection volume Monitor memory usage during tests Fail tests if memory grows unexpectedly Documentation is crucial\nDocument cleanup requirements for event handlers Include lifecycle management in code reviews Create runbooks for common leak patterns Recommendations Immediate Actions:\n✅ Deploy listener removal fix (COMPLETED) ✅ Add memory monitoring alerts (COMPLETED) ✅ Document WebSocket handler lifecycle (COMPLETED) Short-term (1 week):\nAudit all EventEmitter usage across codebase Add automated listener count checks to CI Create memory leak runbook for on-call team Long-term (1 month):\nImplement comprehensive memory testing in CI/CD Build dashboard for real-time listener monitoring Conduct team training on Node.js memory management References Node.js EventEmitter documentation Chrome DevTools Memory Profiling clinic.js documentation Debugging Memory Leaks in Node.js Report Compiled By: DevOps Team\nReviewed By: Engineering Lead\nStatus: Closed\nFollow-up Date: 2026-02-20 (30-day review)\n","permalink":"https://pixcave.com/posts/nodejs-memory-leak-debugging/","summary":"\u003ch2 id=\"incident-report-nodejs-memory-leak-analysis\"\u003eIncident Report: Node.js Memory Leak Analysis\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eDate:\u003c/strong\u003e 2026-01-20\u003cbr\u003e\n\u003cstrong\u003eSeverity:\u003c/strong\u003e P1 (Production Impact)\u003cbr\u003e\n\u003cstrong\u003eMTTR:\u003c/strong\u003e 14 days\u003cbr\u003e\n\u003cstrong\u003eRoot Cause:\u003c/strong\u003e Event listener leak in WebSocket handler\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"timeline-of-events\"\u003eTimeline of Events\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eDay 1 - Jan 6, 09:30 UTC\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eMonitoring alerts: API instances restarting every 6 hours\u003c/li\u003e\n\u003cli\u003eMemory usage shows sawtooth pattern (gradual climb, sudden drop)\u003c/li\u003e\n\u003cli\u003eInitial hypothesis: Database connection leak\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eDay 3 - Jan 8\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRuled out database connections (pool metrics normal)\u003c/li\u003e\n\u003cli\u003eAdded heap profiling to staging environment\u003c/li\u003e\n\u003cli\u003eIdentified EventEmitter instances growing unbounded\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eDay 7 - Jan 13\u003c/strong\u003e\u003c/p\u003e","title":"Node.js Memory Leak: Two Weeks to Find One Missing removeListener()"},{"content":"Common Redis Caching Mistakes (Q\u0026amp;A Format) Q: Our Redis instance is 32GB but our database is only 8GB. Is this normal? A: No, this is a red flag indicating poor cache hygiene.\nWe encountered this exact scenario. Investigation revealed cache entries from:\nUsers inactive for 18+ months Deleted/banned accounts Test accounts from 2023 Orphaned session data Problem root cause: Missing TTL (Time To Live) on cache entries.\n# ❌ Wrong - lives forever redis.set(cache_key, json.dumps(data)) # ✅ Correct - expires after 1 hour redis.setex(cache_key, 3600, json.dumps(data)) Impact: Set appropriate TTLs → 40% memory reduction immediately.\nQ: How do I choose the right TTL value? A: TTL should match data volatility, not be arbitrary.\nOur TTL strategy by data type:\nData Type TTL Rationale User Profile 24h Rarely changes, safe to cache long User Feed 1h Updates frequently, needs freshness Trending Content 5min Real-time requirements Static Content 7d Almost never changes Session Data 30min Security consideration CACHE_TTLS = { \u0026#39;user_profile\u0026#39;: 86400, # 24 hours \u0026#39;user_feed\u0026#39;: 3600, # 1 hour \u0026#39;trending_posts\u0026#39;: 300, # 5 minutes \u0026#39;static_content\u0026#39;: 604800, # 1 week } def cache_set(key, value, data_type=\u0026#39;default\u0026#39;): ttl = CACHE_TTLS.get(data_type, 3600) redis.setex(key, ttl, json.dumps(value)) Testing methodology: Start with conservative (short) TTLs, monitor cache hit rate, adjust incrementally.\nQ: Why are my cache entries so large? A: You\u0026rsquo;re likely caching entire object graphs instead of focused data.\nOur mistake:\n# ❌ Wrong - caches 50KB per post post = db.query(Post).options( joinedload(Post.author), joinedload(Post.comments), # 200 comments! joinedload(Post.tags), joinedload(Post.reactions) # Thousands of reactions ).filter_by(id=post_id).first() redis.set(f\u0026#34;post:{post_id}\u0026#34;, json.dumps(post.to_dict())) Better approach - granular caching:\n# ✅ Correct - cache only what you need def get_post_basic(post_id): \u0026#34;\u0026#34;\u0026#34;Cache just the post (2KB)\u0026#34;\u0026#34;\u0026#34; cache_key = f\u0026#34;post:{post_id}\u0026#34; if cached := redis.get(cache_key): return json.loads(cached) post = db.query(Post).filter_by(id=post_id).first() redis.setex(cache_key, 3600, json.dumps(post.to_dict())) return post def get_post_comments(post_id, limit=20): \u0026#34;\u0026#34;\u0026#34;Separate cache for comments (10KB)\u0026#34;\u0026#34;\u0026#34; comments_key = f\u0026#34;post:{post_id}:comments:{limit}\u0026#34; if cached := redis.get(comments_key): return json.loads(cached) comments = fetch_comments(post_id, limit) redis.setex(comments_key, 600, json.dumps(comments)) return comments Result: 60% cache size reduction. Why? Most API calls need basic post data, not everything.\nQ: What\u0026rsquo;s a cache stampede and how do I prevent it? A: Cache stampede: When popular cache entry expires, hundreds of requests simultaneously hit the database to regenerate it.\nSymptom: Periodic API timeouts coinciding with cache expiration.\nOur incident:\nPopular post cache expired 500 concurrent requests hit database Database connection pool exhausted 10 minute outage Solution - Cache Locking Pattern:\nimport uuid import time def get_with_lock(cache_key, fetch_func, ttl=3600): # Try cache first if cached := redis.get(cache_key): return json.loads(cached) # Attempt lock acquisition lock_key = f\u0026#34;lock:{cache_key}\u0026#34; lock_id = str(uuid.uuid4()) lock_acquired = redis.set( lock_key, lock_id, nx=True, # Only set if doesn\u0026#39;t exist ex=10 # Lock expires in 10 seconds ) if lock_acquired: try: # Winner fetches data data = fetch_func() redis.setex(cache_key, ttl, json.dumps(data)) return data finally: # Release lock with Lua script (atomic) script = \u0026#34;\u0026#34;\u0026#34; if redis.call(\u0026#34;get\u0026#34;, KEYS[1]) == ARGV[1] then return redis.call(\u0026#34;del\u0026#34;, KEYS[1]) end \u0026#34;\u0026#34;\u0026#34; redis.eval(script, 1, lock_key, lock_id) else: # Losers wait and retry time.sleep(0.1) return get_with_lock(cache_key, fetch_func, ttl) Key concepts:\nOnly first request acquires lock and fetches data Other requests wait briefly then retry (data will be cached) Lock timeout prevents deadlocks Atomic lock release prevents race conditions Q: How do I know if my caching strategy is working? A: Measure cache hit rate.\nOur discovery: Cache hit rate was 23%. Terrible. We were wasting resources.\nInstrumentation code:\ndef get_cached(key, fetch_func, ttl=3600): cached = redis.get(key) key_prefix = key.split(\u0026#34;:\u0026#34;)[0] if cached: statsd.increment(\u0026#39;cache.hit\u0026#39;, tags=[f\u0026#39;prefix:{key_prefix}\u0026#39;]) return json.loads(cached) statsd.increment(\u0026#39;cache.miss\u0026#39;, tags=[f\u0026#39;prefix:{key_prefix}\u0026#39;]) data = fetch_func() redis.setex(key, ttl, json.dumps(data)) return data Monitoring dashboard metrics:\nOverall hit rate: hits / (hits + misses) Per-key-type hit rate Memory usage by key prefix Eviction rate Action items from monitoring:\nIdentified cache keys with \u0026lt;10% hit rate → Removed them Found poorly tuned TTLs → Adjusted based on actual access patterns Discovered over-cached data → Implemented granular caching Current metrics: 87% hit rate (target: \u0026gt;80%)\nQ: Should I JSON-encode everything I cache? A: No. Use Redis native data types when appropriate.\nInefficient:\n# ❌ Wrong - unnecessary JSON overhead redis.set(f\u0026#34;counter:{user_id}\u0026#34;, json.dumps(42)) redis.set(f\u0026#34;online_users\u0026#34;, json.dumps([1, 2, 3, 4])) Efficient:\n# ✅ Correct - use native Redis types # Counters redis.incr(f\u0026#34;counter:{user_id}\u0026#34;) # Atomic increment value = int(redis.get(f\u0026#34;counter:{user_id}\u0026#34;)) # Sets redis.sadd(f\u0026#34;online_users\u0026#34;, 1, 2, 3, 4) # No duplicates users = redis.smembers(f\u0026#34;online_users\u0026#34;) # Sorted Sets (leaderboards) redis.zadd(\u0026#34;leaderboard\u0026#34;, {user_id: score}) top10 = redis.zrevrange(\u0026#34;leaderboard\u0026#34;, 0, 9, withscores=True) # Hashes (objects) redis.hset(f\u0026#34;user:{user_id}\u0026#34;, mapping={ \u0026#34;name\u0026#34;: \u0026#34;John\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;john@example.com\u0026#34; }) user_data = redis.hgetall(f\u0026#34;user:{user_id}\u0026#34;) Advantages:\nLess memory (no JSON encoding overhead) Faster operations Atomic operations built-in Type-specific commands (e.g., ZINCRBY, SINTER) Q: What should I cache - the data or the computation? A: Cache the expensive computation result, not intermediate data.\nInefficient approach:\n# ❌ Caching queries, still doing computation def get_reputation_score(user_id): # Cache each query posts = cache_get(f\u0026#34;posts:{user_id}\u0026#34;, lambda: count_posts(user_id)) upvotes = cache_get(f\u0026#34;upvotes:{user_id}\u0026#34;, lambda: count_upvotes(user_id)) comments = cache_get(f\u0026#34;comments:{user_id}\u0026#34;, lambda: count_comments(user_id)) # Still computing this every time! return posts * 5 + upvotes * 2 + comments * 3 Efficient approach:\n# ✅ Cache the final computation def get_reputation_score(user_id): cache_key = f\u0026#34;reputation:{user_id}\u0026#34; if score := redis.get(cache_key): return int(score) # Calculate once posts = count_posts(user_id) upvotes = count_upvotes(user_id) comments = count_comments(user_id) score = posts * 5 + upvotes * 2 + comments * 3 # Cache the result redis.setex(cache_key, 3600, score) return score Principle: Cache what\u0026rsquo;s expensive to compute, not what\u0026rsquo;s expensive to fetch.\nQ: Our team keeps adding cache keys. How do we maintain cache hygiene? A: Implement automated cache analysis.\nOur solution - Weekly audit job:\ndef analyze_cache_patterns(): \u0026#34;\u0026#34;\u0026#34;Analyze cache usage and identify waste\u0026#34;\u0026#34;\u0026#34; cursor = 0 patterns = {} while True: cursor, keys = redis.scan(cursor, count=1000) for key in keys: prefix = key.split(b\u0026#34;:\u0026#34;)[0].decode() ttl = redis.ttl(key) size = len(redis.dump(key)) if prefix not in patterns: patterns[prefix] = { \u0026#39;count\u0026#39;: 0, \u0026#39;total_size\u0026#39;: 0, \u0026#39;no_ttl\u0026#39;: 0 } patterns[prefix][\u0026#39;count\u0026#39;] += 1 patterns[prefix][\u0026#39;total_size\u0026#39;] += size if ttl == -1: # No TTL set patterns[prefix][\u0026#39;no_ttl\u0026#39;] += 1 if cursor == 0: break # Generate report report = [] for prefix, stats in sorted(patterns.items(), key=lambda x: x[1][\u0026#39;total_size\u0026#39;], reverse=True): report.append({ \u0026#39;prefix\u0026#39;: prefix, \u0026#39;key_count\u0026#39;: stats[\u0026#39;count\u0026#39;], \u0026#39;total_mb\u0026#39;: stats[\u0026#39;total_size\u0026#39;] / 1024 / 1024, \u0026#39;keys_without_ttl\u0026#39;: stats[\u0026#39;no_ttl\u0026#39;] }) return report Weekly actions:\nReview top memory consumers Identify keys without TTL Check for orphaned test keys Analyze cache hit rates by prefix Remove unused cache patterns Last week\u0026rsquo;s findings: Removed 2GB of abandoned test data.\nSummary Checklist ✅ Always set TTLs - Match TTL to data volatility\n✅ Cache granularly - Small, focused cache entries\n✅ Prevent stampedes - Use lock patterns for expensive operations\n✅ Monitor continuously - Track hit rate, memory, evictions\n✅ Use native types - Avoid JSON when Redis types suffice\n✅ Cache computation - Not intermediate data\n✅ Audit regularly - Weekly cache hygiene review\nResults After 3 Months Metric Before After Improvement Redis Memory 32GB 9GB -72% Monthly Cost $12,000 $3,000 -75% API Response Time 450ms 120ms -73% Cache Hit Rate 23% 87% +278% Total engineering time invested: ~80 hours\nMonthly savings: $9,000\nROI: Positive after 1 month\nNeed help with Redis optimization? Common issues include: improper TTL strategy, cache stampedes, poor key design, and inadequate monitoring. Address these systematically for best results.\n","permalink":"https://pixcave.com/posts/redis-caching-mistakes/","summary":"\u003ch1 id=\"common-redis-caching-mistakes-qa-format\"\u003eCommon Redis Caching Mistakes (Q\u0026amp;A Format)\u003c/h1\u003e\n\u003ch2 id=\"q-our-redis-instance-is-32gb-but-our-database-is-only-8gb-is-this-normal\"\u003eQ: Our Redis instance is 32GB but our database is only 8GB. Is this normal?\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eA:\u003c/strong\u003e No, this is a red flag indicating poor cache hygiene.\u003c/p\u003e\n\u003cp\u003eWe encountered this exact scenario. Investigation revealed cache entries from:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUsers inactive for 18+ months\u003c/li\u003e\n\u003cli\u003eDeleted/banned accounts\u003c/li\u003e\n\u003cli\u003eTest accounts from 2023\u003c/li\u003e\n\u003cli\u003eOrphaned session data\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eProblem root cause:\u003c/strong\u003e Missing TTL (Time To Live) on cache entries.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ❌ Wrong - lives forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eredis\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eset(cache_key, json\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edumps(data))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ✅ Correct - expires after 1 hour\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eredis\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esetex(cache_key, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e, json\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edumps(data))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eImpact:\u003c/strong\u003e Set appropriate TTLs → 40% memory reduction immediately.\u003c/p\u003e","title":"Redis Caching: The Mistakes That Cost Us $12K/Month"},{"content":"Executive Summary This document analyzes a three-month production deployment of PostgreSQL JSONB columns, documenting performance issues encountered, indexing strategies implemented, and architectural patterns that proved effective. The findings are relevant for teams considering JSONB for schema flexibility in high-traffic applications.\nKey Metrics:\nInitial table size: 2M records Average JSONB column size: 50KB Write throughput: 10K updates/minute Query degradation: 200ms → 14s (70x regression) Background and Context In Q4 2025, our engineering team migrated user preference storage from normalized columns to JSONB format. Primary motivation was reducing schema migration overhead as product requirements evolved.\nInitial Schema Design CREATE TABLE users ( user_id BIGINT PRIMARY KEY, email VARCHAR(255), created_at TIMESTAMP, settings JSONB ); The settings column consolidated 23 previously discrete preference fields.\nPerformance Analysis Phase 1: Initial Deployment (Weeks 1-2) Initial performance metrics were acceptable:\nSELECT queries: \u0026lt;50ms p95 INSERT operations: \u0026lt;30ms p95 Table scan performance: Adequate for 2M records Phase 2: Query Degradation (Week 3) Performance degradation occurred when analytics queries began executing against JSONB fields:\nSELECT settings-\u0026gt;\u0026gt;\u0026#39;signup_source\u0026#39;, COUNT(*) FROM users WHERE settings-\u0026gt;\u0026gt;\u0026#39;created_year\u0026#39; = \u0026#39;2025\u0026#39; GROUP BY settings-\u0026gt;\u0026gt;\u0026#39;signup_source\u0026#39;; Observed Metrics:\nQuery execution time: 14,000ms Sequential scan initiated CPU utilization: 85%+ Root Cause: JSONB columns lack automatic indexing. Queries using -\u0026gt; and -\u0026gt;\u0026gt; operators performed full table scans.\nIndexing Strategies Implemented Strategy 1: GIN Indexes General Inverted (GIN) indexes provide containment query support:\nCREATE INDEX idx_user_settings_gin ON users USING GIN (settings); Performance Characteristics:\nOptimizes: Containment queries (@\u0026gt;, @?, ?) Does not optimize: Value extraction (-\u0026gt;\u0026gt;, #\u0026gt;) Index size overhead: ~15% of column data Strategy 2: Expression Indexes Path-specific indexes for frequently queried fields:\nCREATE INDEX idx_newsletter_sub ON users ((settings-\u0026gt;\u0026gt;\u0026#39;newsletter_subscribed\u0026#39;)); CREATE INDEX idx_region ON users ((settings-\u0026gt;\u0026gt;\u0026#39;region\u0026#39;)); Results:\nQuery time reduction: 14s → 180ms (98% improvement) Total indexes created: 8 Storage overhead: 30% increase Strategy 3: Partial Indexes For queries filtering on specific JSON values:\nCREATE INDEX idx_premium_users ON users ((settings-\u0026gt;\u0026gt;\u0026#39;premium\u0026#39;)) WHERE (settings-\u0026gt;\u0026gt;\u0026#39;premium\u0026#39;) = \u0026#39;true\u0026#39;; Write Amplification Issue Problem Description JSONB updates rewrite the entire column value, not individual fields:\nUPDATE users SET settings = jsonb_set(settings, \u0026#39;{last_login}\u0026#39;, \u0026#39;\u0026#34;2026-01-08\u0026#34;\u0026#39;) WHERE user_id = 12345; Impact Analysis:\nAverage JSONB size: 50KB Update frequency: 10K/minute WAL generation: 500MB/minute Disk I/O saturation observed Solution Architecture Implemented frequency-based column segregation:\nALTER TABLE users ADD COLUMN session_data JSONB, ADD COLUMN profile_settings JSONB; -- Hot data (frequent updates): session_data (~2KB) -- Cold data (rare updates): profile_settings (~48KB) Performance Improvement:\nWrite amplification: -70% WAL generation: 500MB/min → 150MB/min Disk I/O utilization: 90% → 35% Use Case Analysis Recommended Use Cases JSONB is appropriate for:\nVariable User Preferences\nSchema varies significantly per user Read-heavy workload Infrequent updates Audit Logging\nVariable metadata per event Write-once, read-rarely pattern No complex querying requirements API Response Caching\nExternal API responses with variable structure TTL-based data lifecycle Simple key-value retrieval Prototype Development\nSchema in active development Temporary flexibility requirement Migration to normalized schema planned Not Recommended JSONB is inappropriate for:\nHigh-frequency updates to large documents Complex aggregations across JSONB fields Frequently queried fields that could be normalized Critical business data requiring strict schema validation Final Architecture Our production system evolved to a hybrid model:\nCREATE TABLE users ( -- Core fields (normalized) user_id BIGINT PRIMARY KEY, email VARCHAR(255) NOT NULL, created_at TIMESTAMP NOT NULL, -- Volatile state (small JSONB, frequent updates) session_data JSONB, -- User preferences (indexed JSONB, rare updates) profile_settings JSONB ); -- Separate table for historical data CREATE TABLE user_settings_history ( history_id BIGSERIAL PRIMARY KEY, user_id BIGINT REFERENCES users(user_id), settings_snapshot JSONB, created_at TIMESTAMP NOT NULL ) PARTITION BY RANGE (created_at); Current Performance Metrics Query latency: 45ms p95 (restored to baseline) Write throughput: 10K/min (maintained) WAL generation: 150MB/min (70% reduction) Storage efficiency: Acceptable with indexing overhead Lessons Learned Index Strategy is Critical: JSONB requires explicit indexing strategy from day one Write Amplification Real: Update frequency must inform schema design Hybrid Approach Optimal: Combine normalized columns with JSONB selectively Monitor from Start: Implement comprehensive monitoring before production deployment Documentation Essential: PostgreSQL JSONB documentation is comprehensive; invest time upfront Technical Debt Assessment Migration cost comparison:\nOriginal schema migration (5 columns): ~30 minutes with pt-online-schema-change JSONB refactoring effort: ~6 weeks of engineering time Production incident response: ~40 hours Recommendation: Evaluate schema flexibility requirements carefully. Traditional normalized schemas remain appropriate for most use cases.\nReferences PostgreSQL JSONB Documentation: https://www.postgresql.org/docs/current/datatype-json.html GIN Indexes: https://www.postgresql.org/docs/current/gin.html JSONB Indexing Best Practices: PostgreSQL Wiki Document Version: 1.0\nLast Updated: 2026-01-08\nAuthor: Database Engineering Team\nReview Status: Production Validated\n","permalink":"https://pixcave.com/posts/postgres-jsonb-performance-lessons/","summary":"\u003ch2 id=\"executive-summary\"\u003eExecutive Summary\u003c/h2\u003e\n\u003cp\u003eThis document analyzes a three-month production deployment of PostgreSQL JSONB columns, documenting performance issues encountered, indexing strategies implemented, and architectural patterns that proved effective. The findings are relevant for teams considering JSONB for schema flexibility in high-traffic applications.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eKey Metrics:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eInitial table size: 2M records\u003c/li\u003e\n\u003cli\u003eAverage JSONB column size: 50KB\u003c/li\u003e\n\u003cli\u003eWrite throughput: 10K updates/minute\u003c/li\u003e\n\u003cli\u003eQuery degradation: 200ms → 14s (70x regression)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"background-and-context\"\u003eBackground and Context\u003c/h2\u003e\n\u003cp\u003eIn Q4 2025, our engineering team migrated user preference storage from normalized columns to JSONB format. Primary motivation was reducing schema migration overhead as product requirements evolved.\u003c/p\u003e","title":"PostgreSQL JSONB: Three Months of Pain and What I Learned"},{"content":"Took me six months to actually understand RSC. Not the \u0026ldquo;I read the docs\u0026rdquo; understanding - the visceral \u0026ldquo;oh THAT\u0026rsquo;S why\u0026rdquo; moment that only comes from shipping code.\nThe docs make it sound simple: server components render on the server, client components run in the browser. Cool. Useless explanation.\nHere\u0026rsquo;s what actually clicked for me.\nThe mental model that stuck Stop thinking about server vs client components. Think about where the data lives.\nYour component needs data from a database? Server component. Your component needs to respond to a click? Client component. That\u0026rsquo;s it. That\u0026rsquo;s the heuristic.\nEverything else is just implementation details that\u0026rsquo;ll trip you up if you start there.\nThe real code Here\u0026rsquo;s a pattern we use everywhere now:\n// app/dashboard/page.tsx - Server Component (default) async function DashboardPage() { // This is just a regular async function const stats = await db.query.userStats.findMany({ where: eq(schema.userStats.userId, session.userId) }); return ( \u0026lt;div\u0026gt; \u0026lt;StatsGrid data={stats} /\u0026gt; {/* Server Component */} \u0026lt;ChartContainer data={stats} /\u0026gt; {/* Client Component */} \u0026lt;/div\u0026gt; ); } The StatsGrid can stay on the server because it\u0026rsquo;s just rendering HTML. The ChartContainer needs to be a client component because it uses a charting library with interactivity.\n// components/ChartContainer.tsx \u0026#39;use client\u0026#39;; import { LineChart } from \u0026#39;recharts\u0026#39;; export function ChartContainer({ data }: Props) { const [selectedMetric, setSelectedMetric] = useState(\u0026#39;revenue\u0026#39;); return ( \u0026lt;div\u0026gt; \u0026lt;MetricSelector value={selectedMetric} onChange={setSelectedMetric} /\u0026gt; \u0026lt;LineChart data={data} /\u0026gt; \u0026lt;/div\u0026gt; ); } Notice: we\u0026rsquo;re not fetching data in the client component. We\u0026rsquo;re just rendering it. The data comes from the server, flows down as props.\nWhere it gets weird The confusing part is the boundaries. You can\u0026rsquo;t import a server component into a client component directly. This breaks:\n\u0026#39;use client\u0026#39;; import { UserProfile } from \u0026#39;./UserProfile\u0026#39;; // Server component export function Sidebar() { return \u0026lt;UserProfile /\u0026gt;; // ❌ Doesn\u0026#39;t work } But this works:\n// Server component import { Sidebar } from \u0026#39;./Sidebar\u0026#39;; import { UserProfile } from \u0026#39;./UserProfile\u0026#39;; export function Layout() { return ( \u0026lt;Sidebar\u0026gt; \u0026lt;UserProfile /\u0026gt; {/* ✅ Works */} \u0026lt;/Sidebar\u0026gt; ); } // Client component \u0026#39;use client\u0026#39;; export function Sidebar({ children }: { children: React.ReactNode }) { return \u0026lt;div className=\u0026#34;sidebar\u0026#34;\u0026gt;{children}\u0026lt;/div\u0026gt;; } See the difference? The server component (UserProfile) is passed as children. The client component just renders it. It\u0026rsquo;s a slot, not an import.\nThis pattern shows up everywhere once you know to look for it.\nThe performance win that actually matters Everyone talks about bundle size. Yeah, smaller bundles are nice. But the real win is eliminating waterfalls.\nOld pattern (client-side):\n1. Load page JS bundle (1.2s) 2. React hydrates (200ms) 3. useEffect fires 4. Fetch user data (300ms) 5. Fetch related posts (250ms) 6. Render complete Total: ~2s With RSC:\n1. Server fetches both queries in parallel (200ms) 2. Streams HTML to client 3. Client renders instantly Total: ~200ms We cut our dashboard load time from 2.1s to 600ms. Not by optimizing code - just by fetching data on the server where it\u0026rsquo;s closer to the database.\nThe gotchas that actually hurt useState in server components Tried to use useState in a server component? Won\u0026rsquo;t work. Server components run once. No re-renders. If you need state, that component needs to be a client component.\nContext providers Context providers are always client components. So your entire app/layout.tsx becomes a client component if you add a provider there. Solution: create a separate Providers client component and compose it in your server component layout.\n// app/layout.tsx - Server Component import { Providers } from \u0026#39;./providers\u0026#39;; export default function RootLayout({ children }) { return ( \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;Providers\u0026gt;{children}\u0026lt;/Providers\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; ); } // app/providers.tsx - Client Component \u0026#39;use client\u0026#39;; export function Providers({ children }) { return ( \u0026lt;ThemeProvider\u0026gt; \u0026lt;AuthProvider\u0026gt; {children} \u0026lt;/AuthProvider\u0026gt; \u0026lt;/ThemeProvider\u0026gt; ); } Serialization limits You can\u0026rsquo;t pass functions as props from server to client components. Only serializable data. Had a bug where we tried to pass an onClick handler from a server component. TypeScript didn\u0026rsquo;t catch it, runtime did.\nWhen to actually use this Not every app needs RSC. We rebuilt our marketing site with it - huge win. Our internal admin tool? Still using regular React. The admin tool has too much interactivity and not enough database queries to benefit.\nUse RSC when:\nYou have data that changes frequently and you\u0026rsquo;re tired of cache invalidation Your app is mostly content display with some interactive elements SEO matters and you need real server-side rendering Skip it when:\nYou\u0026rsquo;re building a highly interactive app (like Figma or Notion) Your team is still learning React fundamentals You don\u0026rsquo;t have server infrastructure The actual learning curve Took our team about 3 weeks to stop fighting the framework. First week we kept reaching for useEffect to fetch data. Second week we kept putting 'use client' everywhere. Third week it clicked.\nNow we default to server components and only go client when we need interactivity. Code is cleaner, faster, and we spend less time thinking about loading states because the data is just\u0026hellip; there.\nStill feels like magic sometimes. Good magic though.\n","permalink":"https://pixcave.com/posts/react-server-components-explained/","summary":"\u003cp\u003eTook me six months to actually understand RSC. Not the \u0026ldquo;I read the docs\u0026rdquo; understanding - the visceral \u0026ldquo;oh THAT\u0026rsquo;S why\u0026rdquo; moment that only comes from shipping code.\u003c/p\u003e\n\u003cp\u003eThe docs make it sound simple: server components render on the server, client components run in the browser. Cool. Useless explanation.\u003c/p\u003e\n\u003cp\u003eHere\u0026rsquo;s what actually clicked for me.\u003c/p\u003e\n\u003ch2 id=\"the-mental-model-that-stuck\"\u003eThe mental model that stuck\u003c/h2\u003e\n\u003cp\u003eStop thinking about server vs client components. Think about \u003cstrong\u003ewhere the data lives\u003c/strong\u003e.\u003c/p\u003e","title":"React Server Components: I Get It Now"},{"content":"Step-by-Step Guide: Optimizing Docker Build Performance Introduction Problem Statement: Docker builds taking 8+ minutes per PR, causing CI bottlenecks and increased costs.\nSolution Overview: Reduce build time to 40 seconds through multi-stage builds, BuildKit caching, and proper layer optimization.\nWhat You\u0026rsquo;ll Need:\nDocker 20.10+ (for BuildKit support) Basic understanding of Dockerfile syntax A Next.js or Node.js application (examples are adaptable to other frameworks) Expected Time Investment: 2-3 hours for implementation and testing\nStep 1: Diagnose Your Current Build Performance Before optimizing, establish baseline metrics.\n1.1 Measure Current Build Time # Clear all Docker cache docker builder prune -a -f # Time your build time docker build -t myapp:test . Record this time. Our baseline: 8 minutes 15 seconds\n1.2 Identify Cache Invalidation Points # Build once docker build -t myapp:test . # Change a single source file echo \u0026#34;// comment\u0026#34; \u0026gt;\u0026gt; src/index.js # Build again and observe docker build -t myapp:test . Question to answer: Does changing source code trigger npm install to re-run?\nIf yes, your Dockerfile has cache invalidation issues.\n1.3 Analyze Layer Sizes docker history myapp:test --human --no-trunc Look for:\nLayers over 500MB Multiple large node_modules layers Presence of unnecessary files (.git, local node_modules) Step 2: Create a Proper .dockerignore File Purpose: Prevent unnecessary files from invalidating Docker cache.\n2.1 Create .dockerignore in Project Root touch .dockerignore 2.2 Add Essential Exclusions # Dependencies node_modules npm-debug.log* yarn-debug.log* yarn-error.log* # Build output .next dist build out # Development .git .gitignore .env*.local *.log # IDE .vscode .idea .DS_Store # Testing coverage .nyc_output # Documentation README.md CHANGELOG.md docs 2.3 Test Impact # Build and check context size docker build -t myapp:test . 2\u0026gt;\u0026amp;1 | grep \u0026#34;Sending build context\u0026#34; Expected: Context size should drop significantly (e.g., from 800MB to 50MB).\nStep 3: Enable Docker BuildKit Purpose: Access advanced caching features and improved build performance.\n3.1 Enable BuildKit Globally Linux/Mac:\necho \u0026#39;export DOCKER_BUILDKIT=1\u0026#39; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc Windows PowerShell:\n[System.Environment]::SetEnvironmentVariable(\u0026#39;DOCKER_BUILDKIT\u0026#39;, \u0026#39;1\u0026#39;, \u0026#39;User\u0026#39;) 3.2 Enable in CI/CD GitHub Actions:\n- name: Build Docker image run: docker build -t myapp:latest . env: DOCKER_BUILDKIT: 1 GitLab CI:\nbuild: script: - docker build -t myapp:latest . variables: DOCKER_BUILDKIT: 1 3.3 Verify BuildKit is Active docker build -t myapp:test . You should see output format changes (colored, parallel operations shown).\nStep 4: Optimize Dockerfile for Layer Caching Purpose: Separate dependencies from source code to maximize cache reuse.\n4.1 Current Dockerfile (Inefficient) FROM node:18 WORKDIR /app COPY . . # ❌ Copies everything RUN npm install # ❌ Re-runs on any file change RUN npm run build CMD [\u0026#34;npm\u0026#34;, \u0026#34;start\u0026#34;] Problem: Any code change invalidates all subsequent layers.\n4.2 Optimized Dockerfile (Basic) FROM node:18 WORKDIR /app # Copy only dependency files first COPY package.json package-lock.json ./ # Install dependencies (cached unless package files change) RUN npm ci # Then copy source code COPY . . # Build application RUN npm run build CMD [\u0026#34;npm\u0026#34;, \u0026#34;start\u0026#34;] 4.3 Test Improvement # First build time docker build -t myapp:test . # Change source file echo \u0026#34;// test\u0026#34; \u0026gt;\u0026gt; src/index.js # Second build (should be faster) time docker build -t myapp:test . Expected Result: Second build skips npm ci layer.\nStep 5: Implement Multi-Stage Build Purpose: Separate build dependencies from runtime, reducing final image size.\n5.1 Create Multi-Stage Dockerfile # syntax=docker/dockerfile:1.4 # ============================================ # Stage 1: Install production dependencies # ============================================ FROM node:18-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ # Use BuildKit cache mount for npm cache RUN --mount=type=cache,target=/root/.npm \\ npm ci --only=production # ============================================ # Stage 2: Build application # ============================================ FROM node:18-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ # Install all dependencies (including devDependencies) RUN --mount=type=cache,target=/root/.npm \\ npm ci COPY . . # Cache Next.js build cache RUN --mount=type=cache,target=/app/.next/cache \\ npm run build # ============================================ # Stage 3: Production runtime # ============================================ FROM node:18-alpine AS runner WORKDIR /app ENV NODE_ENV=production # Security: Run as non-root user RUN addgroup --system --gid 1001 nodejs \u0026amp;\u0026amp; \\ adduser --system --uid 1001 nextjs # Copy only necessary files 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 3000 CMD [\u0026#34;node\u0026#34;, \u0026#34;server.js\u0026#34;] 5.2 Configure Next.js for Standalone Output Edit next.config.js:\n/** @type {import(\u0026#39;next\u0026#39;).NextConfig} */ const nextConfig = { output: \u0026#39;standalone\u0026#39;, // ... other config } module.exports = nextConfig 5.3 Build and Compare # Build new multi-stage image docker build -t myapp:multi-stage . # Compare sizes docker images | grep myapp Expected Results:\nOld image: ~1200MB New image: ~150MB (87% reduction) Step 6: Configure BuildKit Cache Mounts Purpose: Persist npm cache between builds, avoiding re-downloads.\n6.1 Verify Cache Mount Syntax The --mount=type=cache directive requires:\nDocker BuildKit enabled Syntax directive at top of Dockerfile: # syntax=docker/dockerfile:1.4 6.2 Cache Mount Locations # NPM cache (persists downloaded packages) RUN --mount=type=cache,target=/root/.npm \\ npm ci # Next.js build cache (reuses built pages) RUN --mount=type=cache,target=/app/.next/cache \\ npm run build 6.3 Test Cache Effectiveness # First build (cold cache) docker builder prune -a -f time docker build -t myapp:test . # Second build (warm cache, no changes) time docker build -t myapp:test . Expected: Second build should be significantly faster (8min → 40sec).\nStep 7: Implement Layer Caching in CI Purpose: Persist Docker layers between CI runs.\n7.1 GitHub Actions Configuration Create .github/workflows/docker-build.yml:\nname: Docker Build on: pull_request: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Cache Docker layers uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx- - name: Build Docker image uses: docker/build-push-action@v5 with: context: . push: false tags: myapp:${{ github.sha }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Move cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache 7.2 GitLab CI Configuration Create .gitlab-ci.yml:\nbuild: image: docker:24 services: - docker:24-dind variables: DOCKER_BUILDKIT: 1 DOCKER_DRIVER: overlay2 cache: key: ${CI_COMMIT_REF_SLUG} paths: - .buildx-cache script: - docker buildx create --use - docker buildx build --cache-from type=local,src=.buildx-cache --cache-to type=local,dest=.buildx-cache-new,mode=max -t myapp:${CI_COMMIT_SHA} . - rm -rf .buildx-cache - mv .buildx-cache-new .buildx-cache Step 8: Optimize npm Install Process 8.1 Use npm ci Instead of npm install # ❌ Don\u0026#39;t use: npm install (slower, less predictable) RUN npm install # ✅ Use: npm ci (faster, uses lock file) RUN npm ci Why npm ci:\n2-3x faster than npm install Uses exact versions from lock file Removes node_modules first (clean install) 8.2 Consider Package Manager Alternatives Using pnpm (faster, better caching):\nFROM node:18-alpine AS deps # Install pnpm RUN corepack enable \u0026amp;\u0026amp; corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN --mount=type=cache,target=/root/.local/share/pnpm \\ pnpm install --frozen-lockfile --prod Performance comparison:\nnpm ci: ~120s pnpm install: ~45s (62% faster) Step 9: Implement Build Skipping Purpose: Skip builds when image already exists for current git commit.\n9.1 Tag by Git Commit #!/bin/bash # build.sh GIT_COMMIT=$(git rev-parse --short HEAD) IMAGE_NAME=\u0026#34;myapp:${GIT_COMMIT}\u0026#34; # Check if image exists if docker pull \u0026#34;$IMAGE_NAME\u0026#34; 2\u0026gt;/dev/null; then echo \u0026#34;Image ${IMAGE_NAME} already exists, skipping build\u0026#34; exit 0 fi # Build new image docker build -t \u0026#34;$IMAGE_NAME\u0026#34; . docker push \u0026#34;$IMAGE_NAME\u0026#34; 9.2 CI Integration # GitHub Actions - name: Check if image exists id: check run: | if docker pull myapp:${{ github.sha }} 2\u0026gt;/dev/null; then echo \u0026#34;exists=true\u0026#34; \u0026gt;\u0026gt; $GITHUB_OUTPUT else echo \u0026#34;exists=false\u0026#34; \u0026gt;\u0026gt; $GITHUB_OUTPUT fi - name: Build if needed if: steps.check.outputs.exists == \u0026#39;false\u0026#39; run: docker build -t myapp:${{ github.sha }} . Impact: Saves ~30% of CI builds (re-runs, retries, multiple jobs for same commit).\nStep 10: Monitor and Validate Results 10.1 Build Time Metrics Track these metrics:\n# Build time time docker build -t myapp:test . # Cache hit rate docker build -t myapp:test . 2\u0026gt;\u0026amp;1 | grep \u0026#34;CACHED\u0026#34; # Final image size docker images myapp:test --format \u0026#34;{{.Size}}\u0026#34; 10.2 Create Measurement Script #!/bin/bash # measure-build.sh echo \u0026#34;=== Docker Build Performance Test ===\u0026#34; echo \u0026#34;Date: $(date)\u0026#34; echo \u0026#34;\u0026#34; # Clean build echo \u0026#34;Test 1: Clean build (no cache)\u0026#34; docker builder prune -a -f START=$(date +%s) docker build -t myapp:clean . END=$(date +%s) CLEAN_TIME=$((END - START)) echo \u0026#34;Clean build time: ${CLEAN_TIME}s\u0026#34; echo \u0026#34;\u0026#34; # Cached build (no changes) echo \u0026#34;Test 2: Cached build (no changes)\u0026#34; START=$(date +%s) docker build -t myapp:cached . END=$(date +%s) CACHED_TIME=$((END - START)) echo \u0026#34;Cached build time: ${CACHED_TIME}s\u0026#34; echo \u0026#34;\u0026#34; # Code change build echo \u0026#34;Test 3: Build with code change\u0026#34; echo \u0026#34;// test\u0026#34; \u0026gt;\u0026gt; src/index.js START=$(date +%s) docker build -t myapp:code-change . END=$(date +%s) CODE_CHANGE_TIME=$((END - START)) git restore src/index.js echo \u0026#34;Code change build time: ${CODE_CHANGE_TIME}s\u0026#34; echo \u0026#34;\u0026#34; # Dependency change build echo \u0026#34;Test 4: Build with dependency change\u0026#34; npm install --save-dev lodash START=$(date +%s) docker build -t myapp:dep-change . END=$(date +%s) DEP_CHANGE_TIME=$((END - START)) git restore package.json package-lock.json echo \u0026#34;Dependency change build time: ${DEP_CHANGE_TIME}s\u0026#34; echo \u0026#34;\u0026#34; # Image size IMAGE_SIZE=$(docker images myapp:cached --format \u0026#34;{{.Size}}\u0026#34;) echo \u0026#34;Final image size: ${IMAGE_SIZE}\u0026#34; # Summary echo \u0026#34;\u0026#34; echo \u0026#34;=== Summary ===\u0026#34; echo \u0026#34;Clean build: ${CLEAN_TIME}s\u0026#34; echo \u0026#34;Cached build: ${CACHED_TIME}s ($(echo \u0026#34;scale=1; 100 - ($CACHED_TIME * 100 / $CLEAN_TIME)\u0026#34; | bc)% faster)\u0026#34; echo \u0026#34;Code change build: ${CODE_CHANGE_TIME}s\u0026#34; echo \u0026#34;Dep change build: ${DEP_CHANGE_TIME}s\u0026#34; echo \u0026#34;Image size: ${IMAGE_SIZE}\u0026#34; Run weekly to ensure performance doesn\u0026rsquo;t regress.\nResults Summary Before Optimization Metric Value Clean build time 8min 15s Cached build time 8min 10s (no effective caching) Code change build 8min 5s Image size 1.2GB CI cost/month $400 After Optimization Metric Value Improvement Clean build time 2min 30s -70% Cached build time 40s -92% Code change build 45s -91% Image size 150MB -87% CI cost/month $150 -62% Troubleshooting Guide Issue 1: BuildKit not working Symptom: --mount=type=cache causes errors\nSolution:\n# Verify Docker version (need 20.10+) docker version # Explicitly enable BuildKit export DOCKER_BUILDKIT=1 # Use syntax directive in Dockerfile # syntax=docker/dockerfile:1.4 Issue 2: Cache not persisting in CI Symptom: Every CI build starts from scratch\nSolution:\nVerify cache action is configured correctly Check cache size limits (GitHub Actions: 10GB limit) Ensure cache key includes branch name Use cache-to: type=local,dest=...,mode=max (not mode=min) Issue 3: npm ci fails in Docker Symptom: npm ci errors about missing package-lock.json\nSolution:\n# Ensure you\u0026#39;re copying lock file COPY package.json package-lock.json ./ # Verify lock file exists locally RUN test -f package-lock.json || (echo \u0026#34;Lock file missing\u0026#34; \u0026amp;\u0026amp; exit 1) Issue 4: Large image size persists Symptom: Multi-stage build doesn\u0026rsquo;t reduce size\nSolution:\n# Verify you\u0026#39;re copying FROM correct stage COPY --from=builder /app/.next/standalone ./ # Check Next.js config has standalone output # next.config.js: output: \u0026#39;standalone\u0026#39; # Build and inspect docker build -t myapp:test . docker history myapp:test Next Steps and Advanced Topics Recommended Further Optimizations Registry proxy: Cache layers closer to CI runners pnpm: Switch from npm for better caching Turborepo: If monorepo, use Turborepo for intelligent caching Docker layer caching services: Consider services like Depot.dev Monitoring in Production # Grafana dashboard metrics - docker_build_duration_seconds - docker_build_cache_hits_total - docker_build_cache_misses_total - docker_image_size_bytes - ci_cost_usd Resources Docker BuildKit documentation Next.js Docker deployment Docker layer caching best practices Last Updated: 2026-01-06\nTested With: Docker 24.0, Next.js 14, Node 18\nMaintenance: Re-test after major Docker or framework updates\n","permalink":"https://pixcave.com/posts/docker-build-optimization/","summary":"\u003ch1 id=\"step-by-step-guide-optimizing-docker-build-performance\"\u003eStep-by-Step Guide: Optimizing Docker Build Performance\u003c/h1\u003e\n\u003ch2 id=\"introduction\"\u003eIntroduction\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eProblem Statement:\u003c/strong\u003e Docker builds taking 8+ minutes per PR, causing CI bottlenecks and increased costs.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSolution Overview:\u003c/strong\u003e Reduce build time to 40 seconds through multi-stage builds, BuildKit caching, and proper layer optimization.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWhat You\u0026rsquo;ll Need:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eDocker 20.10+ (for BuildKit support)\u003c/li\u003e\n\u003cli\u003eBasic understanding of Dockerfile syntax\u003c/li\u003e\n\u003cli\u003eA Next.js or Node.js application (examples are adaptable to other frameworks)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eExpected Time Investment:\u003c/strong\u003e 2-3 hours for implementation and testing\u003c/p\u003e","title":"Docker Build Times: From 8 Minutes to 40 Seconds"},{"content":"Rate limiting seems simple until it isn\u0026rsquo;t. We thought we had it figured out - Redis counters, sliding windows, the works. Then a client with a distributed system hit our API and everything fell apart.\nWhat we built initially Standard stuff. Token bucket in Redis:\ndef check_rate_limit(api_key: str) -\u0026gt; bool: key = f\u0026#34;rate_limit:{api_key}\u0026#34; current = redis.get(key) if current and int(current) \u0026gt;= 100: # 100 req/min return False pipe = redis.pipeline() pipe.incr(key) pipe.expire(key, 60) pipe.execute() return True Worked great in testing. 100 requests per minute per API key, clean reset every minute.\nShipped it. Felt smart.\nThe problem Week 2 of production, support ticket: \u0026ldquo;We\u0026rsquo;re getting 429s but we\u0026rsquo;re only making 60 requests per minute.\u0026rdquo;\nWeird. Checked logs. They were indeed making ~60 req/min. But our counter showed 180.\nTurns out they were running the same API key across 3 different servers. Each server was making 60 req/min. Our rate limiter saw 180 req/min from the same key and blocked them.\n\u0026ldquo;Working as intended,\u0026rdquo; I thought. But that\u0026rsquo;s not how customers think. They think in terms of total requests, not requests per origin server.\nAttempt 1: Fix the counter Maybe we just needed better counting:\ndef check_rate_limit(api_key: str, ip: str) -\u0026gt; bool: key = f\u0026#34;rate_limit:{api_key}:{ip}\u0026#34; # ... same logic Now each IP gets its own bucket. Problem solved, right?\nNope. Some clients use load balancers with IP rotation. One request from 1.2.3.4, next from 1.2.3.5. They blew through our limits because each IP got a fresh bucket.\nPlus we couldn\u0026rsquo;t actually enforce account-level limits anymore. A malicious user could just spin up 100 IPs and get 100x the quota.\nWhat actually works We needed to track both:\nPer-API-key total (account-level quota) Per-IP rate (prevent single-IP abuse) But here\u0026rsquo;s the key insight: use different limits for different purposes.\nfrom datetime import datetime, timedelta from typing import Tuple def check_rate_limits(api_key: str, ip: str) -\u0026gt; Tuple[bool, str]: now = datetime.now() minute_key = now.strftime(\u0026#34;%Y-%m-%d:%H:%M\u0026#34;) # Account-level: 1000 req/hour (sliding window) account_key = f\u0026#34;rl:account:{api_key}:{minute_key}\u0026#34; account_count = sum( int(redis.get(f\u0026#34;rl:account:{api_key}:{(now - timedelta(minutes=i)).strftime(\u0026#39;%Y-%m-%d:%H:%M\u0026#39;)}\u0026#34;) or 0) for i in range(60) ) if account_count \u0026gt;= 1000: return False, \u0026#34;Account quota exceeded\u0026#34; # IP-level: 200 req/min (fixed window) ip_key = f\u0026#34;rl:ip:{ip}:{minute_key}\u0026#34; ip_count = int(redis.get(ip_key) or 0) if ip_count \u0026gt;= 200: return False, \u0026#34;IP rate limit exceeded\u0026#34; # Increment both pipe = redis.pipeline() pipe.incr(account_key) pipe.expire(account_key, 3600) # 1 hour pipe.incr(ip_key) pipe.expire(ip_key, 60) # 1 minute pipe.execute() return True, \u0026#34;OK\u0026#34; This is closer but still has issues. That sum() call does 60 Redis GET operations. Doesn\u0026rsquo;t scale.\nThe actual solution: Sorted sets Redis sorted sets let us do sliding windows efficiently:\nimport time def check_rate_limit(api_key: str, ip: str) -\u0026gt; Tuple[bool, str]: now = time.time() minute_ago = now - 60 hour_ago = now - 3600 # Account quota: sliding 1-hour window account_key = f\u0026#34;rl:account:{api_key}\u0026#34; pipe = redis.pipeline() pipe.zremrangebyscore(account_key, 0, hour_ago) # Remove old entries pipe.zcard(account_key) # Count remaining pipe.zadd(account_key, {f\u0026#34;{now}:{ip}\u0026#34;: now}) # Add current request pipe.expire(account_key, 3600) # IP rate: sliding 1-minute window ip_key = f\u0026#34;rl:ip:{ip}\u0026#34; pipe.zremrangebyscore(ip_key, 0, minute_ago) pipe.zcard(ip_key) pipe.zadd(ip_key, {f\u0026#34;{now}:{api_key}\u0026#34;: now}) pipe.expire(ip_key, 60) results = pipe.execute() account_count = results[1] ip_count = results[5] if account_count \u0026gt;= 1000: return False, \u0026#34;Account quota exceeded (1000/hour)\u0026#34; if ip_count \u0026gt;= 200: return False, \u0026#34;Too many requests from IP (200/min)\u0026#34; return True, \u0026#34;OK\u0026#34; Each request adds a timestamped entry to the sorted set. We remove entries older than the window, count what\u0026rsquo;s left, and add the new request. All in one pipeline.\nThis actually works. Sliding windows, accurate counts, handles distributed clients gracefully.\nThe performance catch Sorted sets use more memory than simple counters. For 1M API keys making 1000 req/hour each:\nSimple counters: ~50MB Sorted sets: ~2GB We handled this with Redis memory limits and LRU eviction:\nmaxmemory 4gb maxmemory-policy allkeys-lru If memory gets tight, Redis evicts least-recently-used keys. Which is fine - if an API key hasn\u0026rsquo;t been used in a while, losing its rate limit history doesn\u0026rsquo;t matter. Next request starts fresh.\nBurst handling Some clients have legitimate burst patterns - quiet for 50 minutes, then 800 requests in 5 minutes.\nWe added burst allowance:\ndef check_rate_limit(api_key: str, ip: str) -\u0026gt; Tuple[bool, dict]: # ... existing code ... # Check burst: max 300 req in any 5-minute window five_min_ago = now - 300 pipe.zcount(account_key, five_min_ago, now) # ... execute pipeline ... burst_count = results[8] # From the zcount if burst_count \u0026gt;= 300: return False, { \u0026#34;error\u0026#34;: \u0026#34;Burst limit exceeded\u0026#34;, \u0026#34;limit\u0026#34;: 300, \u0026#34;window\u0026#34;: \u0026#34;5min\u0026#34;, \u0026#34;retry_after\u0026#34;: 60 } This catches abuse while allowing normal traffic spikes.\nResponse headers We added rate limit info to response headers (following GitHub\u0026rsquo;s API pattern):\n@app.after_request def add_rate_limit_headers(response): if hasattr(g, \u0026#39;rate_limit_info\u0026#39;): info = g.rate_limit_info response.headers[\u0026#39;X-RateLimit-Limit\u0026#39;] = info[\u0026#39;limit\u0026#39;] response.headers[\u0026#39;X-RateLimit-Remaining\u0026#39;] = info[\u0026#39;remaining\u0026#39;] response.headers[\u0026#39;X-RateLimit-Reset\u0026#39;] = info[\u0026#39;reset\u0026#39;] return response Clients can see their quota usage without guessing. Support tickets dropped by 40%.\nCost considerations Redis isn\u0026rsquo;t free. We\u0026rsquo;re using ~4GB for rate limiting across all our API keys. On AWS ElastiCache, that\u0026rsquo;s ~$150/month.\nCould we use a cheaper solution? Probably. In-memory counters with sticky sessions, or database-backed rate limiting with caching.\nBut Redis handles our peak load (50K req/sec) without breaking a sweat. The $150/month is worth not waking up at 3am because the rate limiter crashed.\nLessons learned Test with distributed clients. Our initial testing was single-threaded curl requests. Useless.\nDifferent limits for different purposes. Per-IP and per-account limits catch different abuse patterns.\nSliding windows \u0026gt; fixed windows. Users understand \u0026ldquo;1000 per hour\u0026rdquo; better than \u0026ldquo;1000 per hour but it resets at :00.\u0026rdquo;\nReturn helpful error messages. {\u0026quot;error\u0026quot;: \u0026quot;rate limit exceeded\u0026quot;} vs {\u0026quot;error\u0026quot;: \u0026quot;rate limit exceeded\u0026quot;, \u0026quot;retry_after\u0026quot;: 45, \u0026quot;quota_resets\u0026quot;: \u0026quot;2026-01-05T12:00:00Z\u0026quot;} - second one gets way fewer support tickets.\nMemory management matters. Sorted sets eat RAM. Plan for it.\nWould I build this differently today? Maybe use a proper rate limiting service like Upstash or Redis Enterprise. But for our scale, this works. And I understand every line of it, which matters when things go wrong at 3am.\n","permalink":"https://pixcave.com/posts/api-rate-limiter-lessons/","summary":"\u003cp\u003eRate limiting seems simple until it isn\u0026rsquo;t. We thought we had it figured out - Redis counters, sliding windows, the works. Then a client with a distributed system hit our API and everything fell apart.\u003c/p\u003e\n\u003ch2 id=\"what-we-built-initially\"\u003eWhat we built initially\u003c/h2\u003e\n\u003cp\u003eStandard stuff. Token bucket in Redis:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echeck_rate_limit\u003c/span\u003e(api_key: str) \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e bool:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    key \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rate_limit:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003eapi_key\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e redis\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eget(key)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e current \u003cspan style=\"color:#f92672\"\u003eand\u003c/span\u003e int(current) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e:  \u003cspan style=\"color:#75715e\"\u003e# 100 req/min\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eFalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pipe \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e redis\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epipeline()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pipe\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eincr(key)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pipe\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexpire(key, \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pipe\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexecute()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWorked great in testing. 100 requests per minute per API key, clean reset every minute.\u003c/p\u003e","title":"Why Our API Rate Limiter Failed (And How We Fixed It)"},{"content":"Learning TypeScript Generics Through Real Examples Introduction: Why Generics? Let\u0026rsquo;s start with a question I get asked all the time:\n\u0026ldquo;I\u0026rsquo;ve been writing TypeScript for a year, but I still don\u0026rsquo;t really understand generics. Should I just copy-paste them from Stack Overflow?\u0026rdquo;\nShort answer: No. Let me show you why generics exist and when you actually need them.\nPart 1: The Problem Generics Solve Imagine you\u0026rsquo;re building a simple data fetching function. Let\u0026rsquo;s start without generics:\nfunction fetchUser(id: number) { return fetch(`/api/users/${id}`).then(res =\u0026gt; res.json()); } function fetchPost(id: number) { return fetch(`/api/posts/${id}`).then(res =\u0026gt; res.json()); } function fetchComment(id: number) { return fetch(`/api/comments/${id}`).then(res =\u0026gt; res.json()); } Question: What\u0026rsquo;s wrong with this code?\nAnswer:\nLots of repetition No type safety - .json() returns any Have to write new function for every resource type Let\u0026rsquo;s try consolidating:\nfunction fetchData(url: string) { return fetch(url).then(res =\u0026gt; res.json()); } // Usage const user = await fetchData(\u0026#39;/api/users/1\u0026#39;); // Type: any 😞 const post = await fetchData(\u0026#39;/api/posts/1\u0026#39;); // Type: any 😞 Better? Not really. We lost all type information.\nThis is exactly the problem generics solve: We need a way to write flexible functions while maintaining type safety.\nPart 2: Your First Generic Function Here\u0026rsquo;s the same function with generics:\nfunction fetchData\u0026lt;T\u0026gt;(url: string): Promise\u0026lt;T\u0026gt; { return fetch(url).then(res =\u0026gt; res.json()); } // Now we can specify what we\u0026#39;re fetching interface User { id: number; name: string; email: string; } const user = await fetchData\u0026lt;User\u0026gt;(\u0026#39;/api/users/1\u0026#39;); // ✅ user is typed as User, not any! Let\u0026rsquo;s break down the syntax:\nfunction fetchData\u0026lt;T\u0026gt;(url: string): Promise\u0026lt;T\u0026gt; // ^^^ ^^^ // | | // Type parameter Return type uses T Think of \u0026lt;T\u0026gt; as a type variable - similar to how you\u0026rsquo;d use a regular variable:\n// Regular variable function greet(name: string) { return `Hello, ${name}`; } // Type variable function fetchData\u0026lt;T\u0026gt;(url: string): Promise\u0026lt;T\u0026gt; { return fetch(url).then(res =\u0026gt; res.json()); } Just like name is a placeholder for actual string values, T is a placeholder for actual types.\nPart 3: When TypeScript Can Infer Generics Often, you don\u0026rsquo;t need to specify the generic type explicitly:\nfunction identity\u0026lt;T\u0026gt;(value: T): T { return value; } // TypeScript can infer T from the argument const result = identity(\u0026#34;hello\u0026#34;); // T is inferred as string const num = identity(42); // T is inferred as number // You CAN be explicit if you want const explicit = identity\u0026lt;string\u0026gt;(\u0026#34;hello\u0026#34;); Rule of thumb: Let TypeScript infer when possible. Be explicit when necessary (we\u0026rsquo;ll see examples).\nPart 4: Practical Example - React Hook Let\u0026rsquo;s build a realistic custom hook that uses generics:\nWithout generics (bad):\nfunction useApi(url: string) { const [data, setData] = useState\u0026lt;any\u0026gt;(null); const [loading, setLoading] = useState(true); const [error, setError] = useState\u0026lt;Error | null\u0026gt;(null); useEffect(() =\u0026gt; { fetch(url) .then(res =\u0026gt; res.json()) .then(setData) .catch(setError) .finally(() =\u0026gt; setLoading(false)); }, [url]); return { data, loading, error }; // data is any 😞 } // Usage const { data } = useApi(\u0026#39;/api/users/1\u0026#39;); data.name; // No autocomplete, no type checking 😞 With generics (good):\nfunction useApi\u0026lt;T\u0026gt;(url: string) { const [data, setData] = useState\u0026lt;T | null\u0026gt;(null); const [loading, setLoading] = useState(true); const [error, setError] = useState\u0026lt;Error | null\u0026gt;(null); useEffect(() =\u0026gt; { fetch(url) .then(res =\u0026gt; res.json()) .then((data: T) =\u0026gt; setData(data)) .catch(setError) .finally(() =\u0026gt; setLoading(false)); }, [url]); return { data, loading, error }; } // Usage with type safety interface User { id: number; name: string; email: string; } const { data, loading, error } = useApi\u0026lt;User\u0026gt;(\u0026#39;/api/users/1\u0026#39;); if (data) { data.name; // ✅ Autocomplete works! data.email; // ✅ Type checking works! data.foo; // ❌ Error: Property \u0026#39;foo\u0026#39; does not exist } Notice: The generic \u0026lt;T\u0026gt; flows through the entire hook - from the state to the return type.\nPart 5: Multiple Type Parameters Sometimes you need more than one type parameter:\n// Example: A key-value store function createStore\u0026lt;K, V\u0026gt;() { const store = new Map\u0026lt;K, V\u0026gt;(); return { get(key: K): V | undefined { return store.get(key); }, set(key: K, value: V): void { store.set(key, value); }, has(key: K): boolean { return store.has(key); } }; } // Usage const userStore = createStore\u0026lt;number, User\u0026gt;(); userStore.set(1, { id: 1, name: \u0026#39;Alice\u0026#39;, email: \u0026#39;alice@example.com\u0026#39; }); const user = userStore.get(1); // Type: User | undefined const invalid = userStore.get(\u0026#39;1\u0026#39;); // ❌ Error: string is not assignable to number Multiple type parameters let you express relationships between different types in your function.\nPart 6: Generic Constraints Sometimes you need to restrict what types can be used. Enter constraints:\n// Problem: We want to ensure T has an \u0026#39;id\u0026#39; property function findById\u0026lt;T\u0026gt;(items: T[], id: number): T | undefined { return items.find(item =\u0026gt; item.id === id); // ^^^^^^^^ // ❌ Error: Property \u0026#39;id\u0026#39; does not exist on type \u0026#39;T\u0026#39; } Solution: Add a constraint\n// Constraint: T must have an \u0026#39;id\u0026#39; property interface HasId { id: number; } function findById\u0026lt;T extends HasId\u0026gt;(items: T[], id: number): T | undefined { return items.find(item =\u0026gt; item.id === id); // ✅ Now it works! } // Usage interface User extends HasId { name: string; } interface Post extends HasId { title: string; } const users: User[] = [{ id: 1, name: \u0026#39;Alice\u0026#39; }]; const posts: Post[] = [{ id: 1, title: \u0026#39;Hello\u0026#39; }]; findById(users, 1); // ✅ Works findById(posts, 1); // ✅ Works const numbers = [1, 2, 3]; findById(numbers, 1); // ❌ Error: number doesn\u0026#39;t extend HasId The syntax \u0026lt;T extends HasId\u0026gt; means: \u0026ldquo;T can be any type, as long as it has at least an \u0026lsquo;id\u0026rsquo; property.\u0026rdquo;\nPart 7: Real-World Example - Form Handler Let\u0026rsquo;s put it all together with a practical form handling example:\n// Generic form values type type FormValues = Record\u0026lt;string, any\u0026gt;; // Form state interface FormState\u0026lt;T extends FormValues\u0026gt; { values: T; errors: Partial\u0026lt;Record\u0026lt;keyof T, string\u0026gt;\u0026gt;; touched: Partial\u0026lt;Record\u0026lt;keyof T, boolean\u0026gt;\u0026gt;; } // Form actions interface FormActions\u0026lt;T extends FormValues\u0026gt; { setFieldValue: \u0026lt;K extends keyof T\u0026gt;(field: K, value: T[K]) =\u0026gt; void; setFieldError: (field: keyof T, error: string) =\u0026gt; void; setFieldTouched: (field: keyof T, touched: boolean) =\u0026gt; void; resetForm: () =\u0026gt; void; } // The hook function useForm\u0026lt;T extends FormValues\u0026gt;( initialValues: T ): [FormState\u0026lt;T\u0026gt;, FormActions\u0026lt;T\u0026gt;] { const [values, setValues] = useState\u0026lt;T\u0026gt;(initialValues); const [errors, setErrors] = useState\u0026lt;Partial\u0026lt;Record\u0026lt;keyof T, string\u0026gt;\u0026gt;\u0026gt;({}); const [touched, setTouched] = useState\u0026lt;Partial\u0026lt;Record\u0026lt;keyof T, boolean\u0026gt;\u0026gt;\u0026gt;({}); const setFieldValue = \u0026lt;K extends keyof T\u0026gt;(field: K, value: T[K]) =\u0026gt; { setValues(prev =\u0026gt; ({ ...prev, [field]: value })); }; const setFieldError = (field: keyof T, error: string) =\u0026gt; { setErrors(prev =\u0026gt; ({ ...prev, [field]: error })); }; const setFieldTouched = (field: keyof T, touched: boolean) =\u0026gt; { setTouched(prev =\u0026gt; ({ ...prev, [field]: touched })); }; const resetForm = () =\u0026gt; { setValues(initialValues); setErrors({}); setTouched({}); }; return [ { values, errors, touched }, { setFieldValue, setFieldError, setFieldTouched, resetForm } ]; } // Usage - Full type safety! interface LoginForm { email: string; password: string; rememberMe: boolean; } function LoginComponent() { const [form, actions] = useForm\u0026lt;LoginForm\u0026gt;({ email: \u0026#39;\u0026#39;, password: \u0026#39;\u0026#39;, rememberMe: false }); // All of these are type-safe: actions.setFieldValue(\u0026#39;email\u0026#39;, \u0026#39;test@example.com\u0026#39;); // ✅ actions.setFieldValue(\u0026#39;password\u0026#39;, \u0026#39;12345\u0026#39;); // ✅ actions.setFieldValue(\u0026#39;rememberMe\u0026#39;, true); // ✅ actions.setFieldValue(\u0026#39;email\u0026#39;, 123); // ❌ Error: number not assignable to string actions.setFieldValue(\u0026#39;wrongField\u0026#39;, \u0026#39;value\u0026#39;); // ❌ Error: \u0026#39;wrongField\u0026#39; not in LoginForm return ( \u0026lt;form\u0026gt; \u0026lt;input value={form.values.email} onChange={e =\u0026gt; actions.setFieldValue(\u0026#39;email\u0026#39;, e.target.value)} /\u0026gt; {/* Full autocomplete and type checking! */} \u0026lt;/form\u0026gt; ); } What\u0026rsquo;s happening here:\nT extends FormValues - Ensures T is an object type keyof T - Gets all keys of T (\u0026rsquo;email\u0026rsquo; | \u0026lsquo;password\u0026rsquo; | \u0026lsquo;rememberMe\u0026rsquo;) T[K] - Gets the type of a specific field Partial\u0026lt;...\u0026gt; - Makes all properties optional (for errors/touched) Part 8: Common Patterns Cheat Sheet Pattern 1: Array Operations // Get first element with correct type function first\u0026lt;T\u0026gt;(array: T[]): T | undefined { return array[0]; } const nums = [1, 2, 3]; const firstNum = first(nums); // Type: number | undefined const strings = [\u0026#39;a\u0026#39;, \u0026#39;b\u0026#39;, \u0026#39;c\u0026#39;]; const firstStr = first(strings); // Type: string | undefined Pattern 2: Promise Wrapper async function retry\u0026lt;T\u0026gt;( fn: () =\u0026gt; Promise\u0026lt;T\u0026gt;, maxAttempts: number ): Promise\u0026lt;T\u0026gt; { let lastError: Error; for (let i = 0; i \u0026lt; maxAttempts; i++) { try { return await fn(); } catch (error) { lastError = error as Error; } } throw lastError!; } // Usage const user = await retry(() =\u0026gt; fetchData\u0026lt;User\u0026gt;(\u0026#39;/api/users/1\u0026#39;), 3); // Type: User Pattern 3: Builder Pattern class QueryBuilder\u0026lt;T\u0026gt; { private filters: Array\u0026lt;(item: T) =\u0026gt; boolean\u0026gt; = []; where(predicate: (item: T) =\u0026gt; boolean): this { this.filters.push(predicate); return this; } execute(items: T[]): T[] { return items.filter(item =\u0026gt; this.filters.every(filter =\u0026gt; filter(item)) ); } } // Usage interface Product { id: number; name: string; price: number; category: string; } const products: Product[] = [/* ... */]; const result = new QueryBuilder\u0026lt;Product\u0026gt;() .where(p =\u0026gt; p.price \u0026gt; 100) .where(p =\u0026gt; p.category === \u0026#39;electronics\u0026#39;) .execute(products); // Type: Product[] Part 9: When NOT to Use Generics Don\u0026rsquo;t use generics if:\nThe type is always the same // ❌ Unnecessary generic function addNumbers\u0026lt;T extends number\u0026gt;(a: T, b: T): T { return (a + b) as T; } // ✅ Just use number function addNumbers(a: number, b: number): number { return a + b; } You\u0026rsquo;re just avoiding \u0026lsquo;any\u0026rsquo; // ❌ This doesn\u0026#39;t add value function log\u0026lt;T\u0026gt;(value: T): void { console.log(value); } // ✅ This is fine function log(value: unknown): void { console.log(value); } The relationship is too complex If you need 5+ type parameters, reconsider your design.\nPart 10: Debugging Generics When generics don\u0026rsquo;t work as expected, use these techniques:\nTechnique 1: Hover in VS Code Hover over the variable to see what TypeScript inferred:\nconst result = fetchData\u0026lt;User\u0026gt;(\u0026#39;/api/users/1\u0026#39;); // ^^^^^^ Hover to see: const result: Promise\u0026lt;User\u0026gt; Technique 2: Explicit Type Annotations // If inference fails, be explicit const data: User = await fetchData\u0026lt;User\u0026gt;(\u0026#39;/api/users/1\u0026#39;); Technique 3: Use TypeScript Playground Copy your generic code to TypeScript Playground and experiment.\nSummary: The Mental Model Think of generics as function parameters for types:\n// Regular function function greet(name: string) { return `Hello, ${name}`; } greet(\u0026#34;Alice\u0026#34;); // Pass value // Generic function function identity\u0026lt;T\u0026gt;(value: T): T { return value; } identity\u0026lt;string\u0026gt;(\u0026#34;Alice\u0026#34;); // Pass type AND value Key takeaways:\nGenerics let you write reusable code while maintaining type safety Use \u0026lt;T\u0026gt; for single type parameter, \u0026lt;K, V\u0026gt; for multiple Add constraints with extends when needed Let TypeScript infer types when possible Be explicit when inference fails or for clarity Practice Exercise Try converting this code to use generics:\n// Before function getUserById(id: number) { return fetch(`/api/users/${id}`).then(res =\u0026gt; res.json()); } function getPostById(id: number) { return fetch(`/api/posts/${id}`).then(res =\u0026gt; res.json()); } // Your turn: Create a single generic function function getById\u0026lt;T\u0026gt;(resource: string, id: number): Promise\u0026lt;T\u0026gt; { return fetch(`/api/${resource}/${id}`).then(res =\u0026gt; res.json()); } // Usage interface User { id: number; name: string; } interface Post { id: number; title: string; } const user = await getById\u0026lt;User\u0026gt;(\u0026#39;users\u0026#39;, 1); const post = await getById\u0026lt;Post\u0026gt;(\u0026#39;posts\u0026#39;, 1); Next Steps:\nPractice with your own code Read TypeScript handbook on generics Look at popular libraries (React, Redux) to see real-world examples Questions? Leave a comment below!\n","permalink":"https://pixcave.com/posts/typescript-generics-practical-guide/","summary":"\u003ch1 id=\"learning-typescript-generics-through-real-examples\"\u003eLearning TypeScript Generics Through Real Examples\u003c/h1\u003e\n\u003ch2 id=\"introduction-why-generics\"\u003eIntroduction: Why Generics?\u003c/h2\u003e\n\u003cp\u003eLet\u0026rsquo;s start with a question I get asked all the time:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u0026ldquo;I\u0026rsquo;ve been writing TypeScript for a year, but I still don\u0026rsquo;t really understand generics. Should I just copy-paste them from Stack Overflow?\u0026rdquo;\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eShort answer: No. Let me show you why generics exist and when you actually need them.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"part-1-the-problem-generics-solve\"\u003ePart 1: The Problem Generics Solve\u003c/h2\u003e\n\u003cp\u003eImagine you\u0026rsquo;re building a simple data fetching function. Let\u0026rsquo;s start without generics:\u003c/p\u003e","title":"TypeScript Generics: A Practical Guide (No PhD Required)"},{"content":"Indexes are supposed to make queries fast. Sometimes they make them slower. Here\u0026rsquo;s what I wish someone told me before I tanked production performance trying to \u0026ldquo;optimize\u0026rdquo; our database.\nThe query that started it all Support said the admin dashboard was timing out. Found this in the slow query log:\nSELECT * FROM orders WHERE customer_id = 12345 AND status IN (\u0026#39;pending\u0026#39;, \u0026#39;processing\u0026#39;) AND created_at \u0026gt; \u0026#39;2025-12-01\u0026#39; ORDER BY created_at DESC LIMIT 20; Took 8 seconds on a table with 4 million rows. Obviously needs an index, right?\nMy first attempt (the wrong one) CREATE INDEX idx_customer ON orders(customer_id); CREATE INDEX idx_status ON orders(status); CREATE INDEX idx_created ON orders(created_at); Three separate indexes. Seemed logical - we\u0026rsquo;re filtering on all three columns.\nQuery time: 6 seconds.\nWait, what? I added indexes and it only got 20% faster? Checked EXPLAIN:\nEXPLAIN SELECT ... +----+-------------+-------+-------+-----------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+-----------+------+---------+------+------+-------------+ | 1 | SIMPLE | orders| range | idx_created | idx_created | 5 | NULL | 430000 | Using where | +----+-------------+-------+-------+-----------+------+---------+------+------+-------------+ MySQL picked idx_created (the worst choice) and still scanned 430,000 rows. The other two indexes weren\u0026rsquo;t even considered.\nWhy separate indexes suck MySQL can usually only use one index per table. It picks what it thinks is best, and often gets it wrong.\nEven when it uses multiple indexes (index merge), it has to:\nScan first index Scan second index Intersect the row IDs Fetch actual rows This is often slower than scanning without indexes at all.\nThe composite index that worked CREATE INDEX idx_customer_status_created ON orders(customer_id, status, created_at); Query time: 80ms.\nThat\u0026rsquo;s 100x faster. Same query, one index instead of three.\nWhy does this work? Index column order matters. A lot.\nThe leftmost prefix rule Composite indexes work left-to-right. Our index on (customer_id, status, created_at) can help with:\n-- ✅ Uses index WHERE customer_id = 123 -- ✅ Uses index WHERE customer_id = 123 AND status = \u0026#39;pending\u0026#39; -- ✅ Uses index (full) WHERE customer_id = 123 AND status = \u0026#39;pending\u0026#39; AND created_at \u0026gt; \u0026#39;2025-12-01\u0026#39; -- ❌ Can\u0026#39;t use index WHERE status = \u0026#39;pending\u0026#39; -- ❌ Can\u0026#39;t use index WHERE created_at \u0026gt; \u0026#39;2025-12-01\u0026#39; If you don\u0026rsquo;t filter on customer_id (the leftmost column), the index is useless.\nThink of it like a phone book sorted by last name, then first name. You can find \u0026ldquo;Smith, John\u0026rdquo; but you can\u0026rsquo;t quickly find all Johns because first name isn\u0026rsquo;t the primary sort.\nWhen composite indexes backfire We got cocky and added more:\nCREATE INDEX idx_customer_status_created_total ON orders(customer_id, status, created_at, total_amount); CREATE INDEX idx_customer_email_created ON orders(customer_id, email, created_at); Our table went from 2GB to 2.8GB. INSERT performance dropped 30%.\nWhy? Every index has to be updated on every INSERT, UPDATE, and DELETE. More indexes = more write overhead.\nWorse, MySQL\u0026rsquo;s query optimizer got confused. With 8 different indexes, it sometimes picked the wrong one, making queries slower than before.\nThe indexes we actually need After benchmarking real queries, we kept:\nCREATE INDEX idx_customer_created ON orders(customer_id, created_at); CREATE INDEX idx_status_created ON orders(status, created_at); CREATE INDEX idx_email ON orders(email); Three indexes, carefully chosen. Covers 95% of our query patterns.\nThe rule: add indexes for your slowest queries, not every possible query.\nCovering indexes (the secret weapon) Sometimes you can avoid table lookups entirely:\n-- Original query SELECT id, customer_id, status, created_at FROM orders WHERE customer_id = 12345 AND status = \u0026#39;pending\u0026#39;; -- Original index CREATE INDEX idx_customer_status ON orders(customer_id, status); -- EXPLAIN shows \u0026#34;Using index\u0026#34; in Extra column -- MySQL read 50 rows, fetched 50 rows from table -- Covering index CREATE INDEX idx_customer_status_covering ON orders(customer_id, status, id, created_at); -- Now EXPLAIN shows \u0026#34;Using index\u0026#34; (no table access needed) -- MySQL read 50 rows, fetched 0 rows from table A covering index contains all the columns you SELECT, not just the ones you filter on. MySQL can answer the entire query from the index without touching the table.\nThis cut query time from 12ms to 2ms for our most frequent query.\nThe cardinality trap High cardinality = good for indexes. Low cardinality = bad.\n-- Good (high cardinality) CREATE INDEX idx_email ON users(email); -- Each email is unique -- Bad (low cardinality) CREATE INDEX idx_status ON orders(status); -- Only 5 possible statuses -- Terrible (very low cardinality) CREATE INDEX idx_is_active ON users(is_active); -- Only 2 values: true/false MySQL might not even use an index if it thinks a full table scan is faster. With low cardinality columns, it\u0026rsquo;s usually right.\nException: combining low-cardinality columns can work:\nCREATE INDEX idx_type_status ON orders(order_type, status); If order_type has 4 values and status has 5, the combination has 20 possible values. Better, but still not great.\nIndex bloat (the thing that bit us) After 6 months in production, our main index was 400MB but should\u0026rsquo;ve been 200MB. Queries got slower over time.\nThe problem: index fragmentation. DELETEs and UPDATEs leave gaps in the index structure. MySQL doesn\u0026rsquo;t automatically clean this up.\nFix:\n-- Check fragmentation SELECT table_name, index_name, DATA_FREE / DATA_LENGTH as fragmentation_ratio FROM information_schema.TABLES WHERE table_schema = \u0026#39;production\u0026#39;; -- Rebuild indexes OPTIMIZE TABLE orders; OPTIMIZE TABLE rebuilds the table and all its indexes. On a 4M row table, this took 15 minutes and locked the table. We now run it monthly during maintenance windows.\nPartial indexes (MySQL 8+) Sometimes you only care about a subset of data:\nCREATE INDEX idx_active_orders ON orders(customer_id, created_at) WHERE status IN (\u0026#39;pending\u0026#39;, \u0026#39;processing\u0026#39;); Wait, that\u0026rsquo;s PostgreSQL syntax. MySQL doesn\u0026rsquo;t support filtered indexes directly.\nWorkaround: use a generated column:\nALTER TABLE orders ADD COLUMN is_active BOOLEAN GENERATED ALWAYS AS (status IN (\u0026#39;pending\u0026#39;, \u0026#39;processing\u0026#39;)) STORED; CREATE INDEX idx_active ON orders(is_active, customer_id, created_at); Now queries for active orders only scan the relevant index entries. Smaller index = faster queries.\nWhen to skip indexing Don\u0026rsquo;t index:\nSmall tables (\u0026lt; 1000 rows). Full table scan is fine. Columns with very low cardinality (like boolean flags) Tables with heavy writes and rare reads Columns that are always used with functions (WHERE DATE(created_at) = '2025-01-01' can\u0026rsquo;t use an index on created_at) Our audit_logs table has no indexes except the primary key. It\u0026rsquo;s insert-only and we query it once a month. Indexing would just slow down inserts.\nThe reality check Good indexing strategy:\nFind your slowest queries (pg_stat_statements, slow query log) Check if they\u0026rsquo;re missing indexes Add the minimum indexes needed Monitor write performance Drop indexes that aren\u0026rsquo;t being used -- Find unused indexes (MySQL 8+) SELECT object_schema, object_name, index_name FROM performance_schema.table_io_waits_summary_by_index_usage WHERE index_name IS NOT NULL AND count_star = 0 ORDER BY object_schema, object_name; We had 3 indexes with zero usage. Dropped them, saved 200MB and improved insert speed.\nWhat actually matters Column order in composite indexes is critical More indexes != faster queries Indexes have write costs Test with production data volumes Monitor and adjust over time We went from 12 indexes to 6, and overall performance improved. The key was understanding which queries matter and optimizing for those, not trying to optimize every possible query.\nAlso turns out some of our slow queries were slow because of missing LIMIT clauses, not missing indexes. But that\u0026rsquo;s a different story.\n","permalink":"https://pixcave.com/posts/database-indexing-explained/","summary":"\u003cp\u003eIndexes are supposed to make queries fast. Sometimes they make them slower. Here\u0026rsquo;s what I wish someone told me before I tanked production performance trying to \u0026ldquo;optimize\u0026rdquo; our database.\u003c/p\u003e\n\u003ch2 id=\"the-query-that-started-it-all\"\u003eThe query that started it all\u003c/h2\u003e\n\u003cp\u003eSupport said the admin dashboard was timing out. Found this in the slow query log:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e orders\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e customer_id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e12345\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e status \u003cspan style=\"color:#66d9ef\"\u003eIN\u003c/span\u003e (\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;pending\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;processing\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eAND\u003c/span\u003e created_at \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2025-12-01\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eORDER\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eBY\u003c/span\u003e created_at \u003cspan style=\"color:#66d9ef\"\u003eDESC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eLIMIT\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTook 8 seconds on a table with 4 million rows. Obviously needs an index, right?\u003c/p\u003e","title":"Database Indexing: The Stuff Nobody Tells You"},{"content":"Everyone tells you to avoid git rebase. \u0026ldquo;It\u0026rsquo;s dangerous!\u0026rdquo; \u0026ldquo;You\u0026rsquo;ll lose commits!\u0026rdquo; \u0026ldquo;Just merge!\u0026rdquo;\nI used to think that too. Then I joined a team that rebases everything and our git history is actually readable. Here\u0026rsquo;s what changed my mind.\nThe merge commit mess This was our git log before rebasing:\n* Merge branch \u0026#39;feature/user-auth\u0026#39; |\\ | * Fix typo in button text | * Update tests | * Merge main into feature/user-auth | |\\ | |/ |/| * | Merge branch \u0026#39;fix/header-spacing\u0026#39; |\\ \\ | * | Adjust header margin * | | Merge branch \u0026#39;feature/notifications\u0026#39; |\\| | | |/ |/| See those merge commits? They add zero value. Just noise. Finding where a feature was added means clicking through 5 merge commits.\nAfter switching to rebase:\n* Add notification system * Adjust header margin * Fix typo in button text * Update tests * Add user authentication Linear history. Each commit is an actual change. No merge cruft.\nHow rebase actually works Stop thinking about it as \u0026ldquo;scary surgery.\u0026rdquo; Think about it as \u0026ldquo;replay commits on a newer base.\u0026rdquo;\nYou have a feature branch:\nmain: A---B---C \\ feature: D---E Someone merged changes to main:\nmain: A---B---C---F---G \\ feature: D---E Merging creates a merge commit:\nmain: A---B---C---F---G---M \\ / feature: D-----E----- Rebasing replays your commits on top of the latest main:\nmain: A---B---C---F---G \\ feature: D\u0026#39;---E\u0026#39; Your commits D and E are replayed as D\u0026rsquo; and E\u0026rsquo;. Same changes, different base.\nThe basic workflow This is what I do every day:\n# Update main git checkout main git pull # Rebase my feature branch git checkout feature/user-profile git rebase main If there are no conflicts, done. Your feature branch now has all the latest main changes and maintains linear history.\nHandling conflicts This is where people panic. Don\u0026rsquo;t.\ngit rebase main # CONFLICT (content): Merge conflict in user.ts Git pauses the rebase. You fix the conflict like you would in a merge:\n# Open the conflicting file code user.ts # Fix the conflict, then: git add user.ts git rebase --continue Git replays the next commit. If there\u0026rsquo;s another conflict, repeat. If you mess up:\ngit rebase --abort This cancels everything and returns your branch to the state before you started.\nInteractive rebase (the power tool) This is where rebase gets really useful:\ngit rebase -i HEAD~5 Opens an editor showing your last 5 commits:\npick a1b2c3d Add user model pick d4e5f6g Add user routes pick h7i8j9k Fix typo pick k0l1m2n Update tests pick n3o4p5q Fix typo again You can:\nReword: Change commit message Edit: Stop and modify the commit Squash: Combine with previous commit Fixup: Squash but discard this commit message Drop: Delete this commit Let\u0026rsquo;s clean this up:\npick a1b2c3d Add user model pick d4e5f6g Add user routes fixup h7i8j9k Fix typo pick k0l1m2n Update tests fixup n3o4p5q Fix typo again Result: 5 commits become 3 clean commits. No \u0026ldquo;Fix typo\u0026rdquo; commits in the history.\nWhen to squash I squash:\nTypo fixes \u0026ldquo;Oops forgot to add file\u0026rdquo; commits \u0026ldquo;WIP\u0026rdquo; commits Multiple commits that are really one logical change I keep separate:\nDifferent features Separate bug fixes Refactoring vs feature work Example: adding a login feature might end up as one commit \u0026ldquo;Add user authentication\u0026rdquo; instead of 8 commits including \u0026ldquo;Fix lint error\u0026rdquo; and \u0026ldquo;Update test snapshot.\u0026rdquo;\nThe golden rule Never rebase commits that have been pushed to shared branches.\nIf someone else has pulled your commits, rebasing rewrites history and causes chaos. They\u0026rsquo;ll have a diverged history and merging becomes a nightmare.\nSafe:\n# Your feature branch, not pushed yet git rebase main git push origin feature/user-profile Also safe:\n# Your feature branch, pushed but nobody else has pulled it git rebase main git push origin feature/user-profile --force-with-lease Dangerous:\n# main branch that others have pulled git checkout main git rebase feature/something # DON\u0026#39;T DO THIS \u0026ndash;force-with-lease Don\u0026rsquo;t use --force. Use --force-with-lease:\ngit push --force-with-lease This only force-pushes if nobody else has pushed to the branch since your last pull. If they have, it fails instead of overwriting their work.\nSaved me from overwriting a teammate\u0026rsquo;s commits at least twice.\nAborting mid-rebase Got halfway through a rebase and realized you\u0026rsquo;re screwed? Abort:\ngit rebase --abort This is way easier than trying to fix a broken merge. Hit abort, take a breath, try again.\nIf you already finished the rebase but want to undo it:\ngit reflog # Find the commit before the rebase (like HEAD@{3}) git reset --hard HEAD@{3} Rebasing vs merging When to merge:\nMerging main into main Integrating long-running feature branches When you want to preserve exact history of parallel work When to rebase:\nUpdating your feature branch with latest main Cleaning up commits before PR When you want linear history We use both. Rebase for feature branches, merge for main. Gives us clean feature branches and preserved integration points.\nThe autosquash trick Add this to your .gitconfig:\n[rebase] autoSquash = true Now you can:\ngit commit -m \u0026#34;Add user model\u0026#34; # ... later ... git commit --fixup a1b2c3d # References the first commit hash When you git rebase -i --autosquash main, git automatically marks fixup commits for squashing. No manual editing needed.\nDealing with binary conflicts The worst: merge conflicts in package-lock.json or yarn.lock.\nDon\u0026rsquo;t resolve them manually. Do this:\ngit rebase main # CONFLICT in package-lock.json git checkout --theirs package-lock.json # Use their version npm install # Regenerate lock file git add package-lock.json git rebase --continue Trying to manually merge package-lock.json is pointless. Just regenerate it.\nMy actual workflow # Start feature git checkout -b feature/thing # ... work work work ... git add -p # Stage changes interactively git commit -m \u0026#34;WIP: thing\u0026#34; # Iterate # ... more work ... git commit --amend # Add to previous commit instead of new WIP commit # Before pushing git rebase -i main # Clean up commits git push origin feature/thing # Update feature with latest main git fetch origin git rebase origin/main git push --force-with-lease The key: clean up before pushing. Once it\u0026rsquo;s pushed, be more careful. But while it\u0026rsquo;s local, rebase freely.\nWhen rebase saved our ass We had a bug in main. Fixed it, but 4 feature branches were based on the buggy code.\nWith merging, each branch would merge the buggy main, then we\u0026rsquo;d merge the fix into each branch. Then merge the branches back to main. Git graph looked like spaghetti.\nWith rebasing:\n# For each feature branch: git checkout feature/whatever git rebase main # Gets the bug fix automatically Linear history, bug fixed in all branches, no merge commit soup.\nWhat actually matters Rebase isn\u0026rsquo;t scary if you:\nUnderstand it replays commits, doesn\u0026rsquo;t delete them Use \u0026ndash;abort when things go wrong Don\u0026rsquo;t rebase shared history Practice on a test repo first The git history cleanup alone is worth it. When you need to find when a bug was introduced, linear history makes git bisect actually useful. Good luck bisecting through 50 merge commits.\nTry it on a feature branch. If it goes wrong, git rebase --abort. If it goes really wrong, git reflog can save you. You\u0026rsquo;ll probably never go back to merge-only workflows.\n","permalink":"https://pixcave.com/posts/git-rebase-demystified/","summary":"\u003cp\u003eEveryone tells you to avoid \u003ccode\u003egit rebase\u003c/code\u003e. \u0026ldquo;It\u0026rsquo;s dangerous!\u0026rdquo; \u0026ldquo;You\u0026rsquo;ll lose commits!\u0026rdquo; \u0026ldquo;Just merge!\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eI used to think that too. Then I joined a team that rebases everything and our git history is actually readable. Here\u0026rsquo;s what changed my mind.\u003c/p\u003e\n\u003ch2 id=\"the-merge-commit-mess\"\u003eThe merge commit mess\u003c/h2\u003e\n\u003cp\u003eThis was our git log before rebasing:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e* Merge branch \u0026#39;feature/user-auth\u0026#39;\n|\\\n| * Fix typo in button text\n| * Update tests\n| * Merge main into feature/user-auth\n| |\\\n| |/\n|/|\n* | Merge branch \u0026#39;fix/header-spacing\u0026#39;\n|\\ \\\n| * | Adjust header margin\n* | | Merge branch \u0026#39;feature/notifications\u0026#39;\n|\\| |\n| |/\n|/|\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eSee those merge commits? They add zero value. Just noise. Finding where a feature was added means clicking through 5 merge commits.\u003c/p\u003e","title":"Git Rebase: Stop Being Scared of It"},{"content":"We send about 10 million webhooks per day now. Started at 100K/day a year ago. Thought it would scale fine. It didn\u0026rsquo;t. Here\u0026rsquo;s everything that broke and how we fixed it.\nThe naive implementation def send_webhook(event_type, payload, url): try: requests.post( url, json={\u0026#34;event\u0026#34;: event_type, \u0026#34;data\u0026#34;: payload}, timeout=5 ) except Exception: # ¯\\_(ツ)_/¯ pass Call this function whenever something happens. Fire and forget. What could go wrong?\nProblem 1: Blocking the main thread Webhook delivery was part of the request cycle. User creates an order, we save it, then send webhooks to their configured endpoints. If their endpoint is down or slow, the user\u0026rsquo;s request times out.\nCustomer reported checkout taking 30 seconds. Their webhook endpoint was timing out but we waited the full 5 seconds before giving up.\nFix: Move to background jobs.\nfrom celery import shared_task @shared_task def send_webhook_async(event_type, payload, url): try: response = requests.post( url, json={\u0026#34;event\u0026#34;: event_type, \u0026#34;data\u0026#34;: payload}, timeout=5 ) response.raise_for_status() except requests.exceptions.RequestException as e: # Still swallowing errors but at least not blocking users logger.error(f\u0026#34;Webhook failed: {e}\u0026#34;) Now webhook delivery happens in Celery workers, not during the request. User checkouts are fast again.\nProblem 2: No retries Webhooks failed silently. Customer endpoints go down for maintenance? They miss events permanently.\nAdded retries with exponential backoff:\n@shared_task(bind=True, max_retries=5) def send_webhook_async(self, event_type, payload, url, attempt=0): try: response = requests.post( url, json={\u0026#34;event\u0026#34;: event_type, \u0026#34;data\u0026#34;: payload}, timeout=5, headers={\u0026#34;X-Webhook-Attempt\u0026#34;: str(attempt + 1)} ) response.raise_for_status() except requests.exceptions.RequestException as e: # Retry with exponential backoff: 1min, 5min, 25min, 2h, 10h self.retry(exc=e, countdown=60 * (5 ** attempt)) Better, but created a new problem.\nProblem 3: Retry storms A popular customer\u0026rsquo;s endpoint went down. We had 50K webhooks queued for them. All 50K retried at the same time after 1 minute. Their endpoint came back up, got hit with 50K requests in 10 seconds, went down again.\nRetry storm. Classic distributed systems problem.\nSolution: Add jitter and rate limiting per endpoint.\nimport random from datetime import datetime, timedelta @shared_task(bind=True, max_retries=5) def send_webhook_async(self, event_type, payload, url, webhook_id, attempt=0): # Rate limit: max 100 req/min per endpoint rate_limit_key = f\u0026#34;webhook:ratelimit:{hash(url)}\u0026#34; current_count = redis.incr(rate_limit_key) if current_count == 1: redis.expire(rate_limit_key, 60) if current_count \u0026gt; 100: # Back off if we\u0026#39;re sending too fast self.retry(countdown=random.randint(60, 120)) return try: response = requests.post(url, json={ \u0026#34;event\u0026#34;: event_type, \u0026#34;data\u0026#34;: payload, \u0026#34;webhook_id\u0026#34;: webhook_id, \u0026#34;attempt\u0026#34;: attempt + 1 }, timeout=10) response.raise_for_status() # Log success redis.hincrby(\u0026#34;webhook:stats\u0026#34;, \u0026#34;success\u0026#34;, 1) except requests.exceptions.RequestException as e: # Add jitter to retry timing base_delay = 60 * (5 ** attempt) jitter = random.randint(0, base_delay // 2) self.retry(exc=e, countdown=base_delay + jitter) Now retries are spread out over time and we don\u0026rsquo;t hammer any single endpoint.\nProblem 4: No delivery guarantees Webhooks still got lost. Celery workers crashed, Redis went down, tasks vanished.\nMoved to a proper queue with persistence:\n# Store webhook in database first webhook = Webhook.objects.create( event_type=event_type, payload=payload, url=url, status=\u0026#39;pending\u0026#39; ) # Then queue for delivery send_webhook_async.delay(webhook.id) @shared_task(bind=True, max_retries=5) def send_webhook_async(self, webhook_id, attempt=0): webhook = Webhook.objects.get(id=webhook_id) if webhook.status == \u0026#39;delivered\u0026#39;: return # Already delivered, skip try: response = requests.post(webhook.url, json={ \u0026#34;event\u0026#34;: webhook.event_type, \u0026#34;data\u0026#34;: webhook.payload, \u0026#34;id\u0026#34;: str(webhook.id), \u0026#34;attempt\u0026#34;: attempt + 1 }, timeout=10) if response.status_code == 200: webhook.status = \u0026#39;delivered\u0026#39; webhook.delivered_at = timezone.now() webhook.save() else: raise Exception(f\u0026#34;HTTP {response.status_code}\u0026#34;) except Exception as e: webhook.attempts += 1 webhook.last_error = str(e) webhook.save() if attempt \u0026gt;= 4: # Final retry webhook.status = \u0026#39;failed\u0026#39; webhook.save() else: self.retry(exc=e, countdown=60 * (5 ** attempt) + random.randint(0, 300)) Now we have a source of truth. If a webhook wasn\u0026rsquo;t delivered, we know about it.\nProblem 5: Database bottleneck 10M webhooks/day = ~115 per second. Each webhook is 2 DB writes (create + update on success/fail). That\u0026rsquo;s 230 writes/second to one table.\nDatabase started struggling. Connection pool maxed out. Queries queued.\nOptimization 1: Batch updates\n# Instead of updating each webhook individually # Collect successful webhook IDs in Redis redis.sadd(f\u0026#34;webhook:batch:success:{minute}\u0026#34;, webhook_id) # Separate job runs every minute @periodic_task(run_every=timedelta(minutes=1)) def batch_update_webhooks(): minute = datetime.now().strftime(\u0026#34;%Y-%m-%d:%H:%M\u0026#34;) success_ids = redis.smembers(f\u0026#34;webhook:batch:success:{minute}\u0026#34;) if success_ids: Webhook.objects.filter(id__in=success_ids).update( status=\u0026#39;delivered\u0026#39;, delivered_at=timezone.now() ) redis.delete(f\u0026#34;webhook:batch:success:{minute}\u0026#34;) Reduced DB writes by 80%. Single batch update instead of individual updates.\nOptimization 2: Partition the table\n-- PostgreSQL partitioning by month CREATE TABLE webhooks ( id BIGSERIAL, created_at TIMESTAMP, -- other fields ) PARTITION BY RANGE (created_at); CREATE TABLE webhooks_2026_01 PARTITION OF webhooks FOR VALUES FROM (\u0026#39;2026-01-01\u0026#39;) TO (\u0026#39;2026-02-01\u0026#39;); CREATE TABLE webhooks_2026_02 PARTITION OF webhooks FOR VALUES FROM (\u0026#39;2026-02-01\u0026#39;) TO (\u0026#39;2026-03-01\u0026#39;); Queries only scan relevant partitions. Old partitions can be archived without affecting current data.\nProblem 6: Webhook signature verification Customers asked \u0026ldquo;how do we know webhooks are really from you?\u0026rdquo;\nAdded HMAC signatures:\nimport hmac import hashlib def send_webhook_async(webhook_id): webhook = Webhook.objects.get(id=webhook_id) customer = webhook.customer payload = json.dumps({ \u0026#34;event\u0026#34;: webhook.event_type, \u0026#34;data\u0026#34;: webhook.payload, \u0026#34;id\u0026#34;: str(webhook.id), \u0026#34;timestamp\u0026#34;: int(time.time()) }) # Sign with customer\u0026#39;s secret key signature = hmac.new( customer.webhook_secret.encode(), payload.encode(), hashlib.sha256 ).hexdigest() response = requests.post( webhook.url, data=payload, headers={ \u0026#34;Content-Type\u0026#34;: \u0026#34;application/json\u0026#34;, \u0026#34;X-Webhook-Signature\u0026#34;: f\u0026#34;sha256={signature}\u0026#34;, \u0026#34;X-Webhook-ID\u0026#34;: str(webhook.id) }, timeout=10 ) Customers verify signatures on their end:\n# Customer\u0026#39;s webhook receiver def verify_webhook(request): payload = request.body signature = request.headers.get(\u0026#34;X-Webhook-Signature\u0026#34;) expected = hmac.new( SECRET_KEY.encode(), payload, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(f\u0026#34;sha256={expected}\u0026#34;, signature): return HttpResponse(status=401) # Process webhook Problem 7: Observability When webhooks failed, we had no visibility. Is our system broken or is the customer\u0026rsquo;s endpoint down?\nAdded comprehensive logging:\n# Log attempt logger.info(\u0026#34;webhook.attempt\u0026#34;, extra={ \u0026#34;webhook_id\u0026#34;: webhook.id, \u0026#34;customer_id\u0026#34;: webhook.customer_id, \u0026#34;event_type\u0026#34;: webhook.event_type, \u0026#34;attempt\u0026#34;: attempt, \u0026#34;url\u0026#34;: webhook.url }) # Log result logger.info(\u0026#34;webhook.delivered\u0026#34;, extra={ \u0026#34;webhook_id\u0026#34;: webhook.id, \u0026#34;duration_ms\u0026#34;: (time.time() - start) * 1000, \u0026#34;status_code\u0026#34;: response.status_code }) # Or on failure logger.warning(\u0026#34;webhook.failed\u0026#34;, extra={ \u0026#34;webhook_id\u0026#34;: webhook.id, \u0026#34;error\u0026#34;: str(e), \u0026#34;will_retry\u0026#34;: attempt \u0026lt; 4 }) Structured logging feeds into Datadog. We built dashboards showing:\nDelivery rate by customer Failed webhooks by error type Average delivery time Retry success rate Now when a customer reports missing webhooks, we can see exactly what happened.\nThe current architecture User action ↓ Create webhook record (DB) ↓ Queue webhook (Redis/Celery) ↓ Worker picks up task ↓ Rate limit check (Redis) ↓ Send HTTP request ↓ Success? → Batch update DB ↓ Failure? → Retry with backoff ↓ Max retries exceeded? → Mark as failed, alert customer Handles 10M/day without breaking a sweat. Could probably scale to 100M/day with more workers.\nWhat actually matters Don\u0026rsquo;t block user requests - webhooks must be async Retries are mandatory - networks are unreliable Add jitter to retries - prevent thundering herds Persist everything - queues can lose data Rate limit per endpoint - protect customer servers Sign your webhooks - customers need to verify authenticity Batch database writes - individual updates don\u0026rsquo;t scale Log everything - you\u0026rsquo;ll need it for debugging We went from constant webhook issues to a system that just works. The key was treating webhooks as a first-class feature with proper architecture, not an afterthought.\nAlso learned that most webhook receivers are terribly implemented. We\u0026rsquo;ve seen endpoints that return 200 but don\u0026rsquo;t actually process the webhook, endpoints that hang for 60 seconds, endpoints that crash on duplicate deliveries. Plan for that.\n","permalink":"https://pixcave.com/posts/webhooks-at-scale/","summary":"\u003cp\u003eWe send about 10 million webhooks per day now. Started at 100K/day a year ago. Thought it would scale fine. It didn\u0026rsquo;t. Here\u0026rsquo;s everything that broke and how we fixed it.\u003c/p\u003e\n\u003ch2 id=\"the-naive-implementation\"\u003eThe naive implementation\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esend_webhook\u003c/span\u003e(event_type, payload, url):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        requests\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epost(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            url,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            json\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;event\u0026#34;\u003c/span\u003e: event_type, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;data\u0026#34;\u003c/span\u003e: payload},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexcept\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eException\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# ¯\\_(ツ)_/¯\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003epass\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCall this function whenever something happens. Fire and forget. What could go wrong?\u003c/p\u003e\n\u003ch2 id=\"problem-1-blocking-the-main-thread\"\u003eProblem 1: Blocking the main thread\u003c/h2\u003e\n\u003cp\u003eWebhook delivery was part of the request cycle. User creates an order, we save it, then send webhooks to their configured endpoints. If their endpoint is down or slow, the user\u0026rsquo;s request times out.\u003c/p\u003e","title":"Webhooks at Scale: What We Learned Sending 10M/Day"},{"content":"Found our AWS access keys in a public GitHub repo last month. Fun times. Here\u0026rsquo;s how it happened and what we actually did to prevent it.\nHow we leaked them Developer needed to add an API key to a Kubernetes service. Did this:\n# deployment.yaml - DON\u0026#39;T DO THIS apiVersion: apps/v1 kind: Deployment metadata: name: api-service spec: template: spec: containers: - name: api env: - name: AWS_ACCESS_KEY value: \u0026#34;AKIAIOSFODNN7EXAMPLE\u0026#34; # 🚨 Plaintext in git! - name: AWS_SECRET_KEY value: \u0026#34;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\u0026#34; Committed it. Pushed it. Public repo. Keys were active for 6 hours before AWS alerted us to unusual activity.\nSomeone spun up 50 EC2 instances mining cryptocurrency. $2,400 bill.\nThe \u0026ldquo;obvious\u0026rdquo; fix that doesn\u0026rsquo;t work \u0026ldquo;Just use Kubernetes Secrets!\u0026rdquo;\napiVersion: v1 kind: Secret metadata: name: aws-creds type: Opaque data: access-key: QUTJQVBMRERKWVVXNUZXM0lG # Base64 encoded secret-key: NVBuREJaeE5wRUxhMkJKSGxNMlpmajNx # deployment.yaml env: - name: AWS_ACCESS_KEY valueFrom: secretKeyRef: name: aws-creds key: access-key Better, right? Nope. Kubernetes Secrets are just base64 encoded, not encrypted. Anyone with kubectl access can decode them:\nkubectl get secret aws-creds -o yaml # Copy the base64 string echo \u0026#34;QUTJQVBMRERKWVVXNUZXM0lG\u0026#34; | base64 -d # AKIAIOSFODNN7EXAMPLE Also, the Secret itself is still committed to git. Just base64 encoded instead of plaintext. Security theater.\nWhat actually works: External secret management We moved to AWS Secrets Manager with External Secrets Operator.\n# First, store secret in AWS Secrets Manager (CLI or Console) aws secretsmanager create-secret \\ --name prod/aws-creds \\ --secret-string \u0026#39;{\u0026#34;access_key\u0026#34;:\u0026#34;AKIA...\u0026#34;,\u0026#34;secret_key\u0026#34;:\u0026#34;wJal...\u0026#34;}\u0026#39; # Install External Secrets Operator in cluster helm install external-secrets \\ external-secrets/external-secrets \\ -n external-secrets-system \\ --create-namespace # Create SecretStore (points to AWS Secrets Manager) apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: aws-secretsmanager namespace: production spec: provider: aws: service: SecretsManager region: us-east-1 auth: jwt: serviceAccountRef: name: external-secrets-sa # Uses IAM role via IRSA # Create ExternalSecret (syncs from AWS) apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-creds namespace: production spec: refreshInterval: 1h secretStoreRef: name: aws-secretsmanager kind: SecretStore target: name: aws-creds # Creates this Kubernetes Secret data: - secretKey: access-key remoteRef: key: prod/aws-creds property: access_key - secretKey: secret-key remoteRef: key: prod/aws-creds property: secret_key Now:\nSecrets live in AWS Secrets Manager (encrypted at rest) External Secrets Operator syncs them to K8s Nothing sensitive in git Secrets can be rotated in AWS and automatically update in K8s The IRSA setup (critical) External Secrets needs permission to read from Secrets Manager. Don\u0026rsquo;t hardcode AWS credentials. Use IAM Roles for Service Accounts (IRSA).\n# Create IAM policy cat \u0026gt; secrets-policy.json \u0026lt;\u0026lt;EOF { \u0026#34;Version\u0026#34;: \u0026#34;2012-10-17\u0026#34;, \u0026#34;Statement\u0026#34;: [{ \u0026#34;Effect\u0026#34;: \u0026#34;Allow\u0026#34;, \u0026#34;Action\u0026#34;: [ \u0026#34;secretsmanager:GetSecretValue\u0026#34;, \u0026#34;secretsmanager:DescribeSecret\u0026#34; ], \u0026#34;Resource\u0026#34;: \u0026#34;arn:aws:secretsmanager:us-east-1:*:secret:prod/*\u0026#34; }] } EOF aws iam create-policy \\ --policy-name ExternalSecretsPolicy \\ --policy-document file://secrets-policy.json # Create IAM role for service account eksctl create iamserviceaccount \\ --name external-secrets-sa \\ --namespace external-secrets-system \\ --cluster production-cluster \\ --attach-policy-arn arn:aws:iam::123456789:policy/ExternalSecretsPolicy \\ --approve Now the External Secrets operator uses the IAM role, no credentials needed.\nSecret rotation With AWS Secrets Manager, rotation is automated:\naws secretsmanager rotate-secret \\ --secret-id prod/aws-creds \\ --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789:function:RotateSecrets \\ --rotation-rules AutomaticallyAfterDays=30 External Secrets Operator detects the change (checks every hour) and updates the K8s Secret. Pods pick up the new secret automatically via environment variable refresh or volume mount reload.\nEncrypting Secrets at rest in etcd Even with External Secrets, K8s stores the synced Secrets in etcd. By default, etcd doesn\u0026rsquo;t encrypt.\nEnable encryption at rest:\n# encryption-config.yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: \u0026lt;base64-32-byte-key\u0026gt; - identity: {} # Fallback for unencrypted data # Generate encryption key head -c 32 /dev/urandom | base64 # Apply to API server kube-apiserver \\ --encryption-provider-config=/etc/kubernetes/encryption-config.yaml \\ ... Now secrets in etcd are encrypted with AES-CBC. Even if someone dumps etcd, they can\u0026rsquo;t read secrets.\nWhat we don\u0026rsquo;t commit to git # .gitignore for K8s repos *.secret.yaml secrets/ credentials/ .env* kubeconfig *.key *.pem Our CI/CD applies secrets from AWS Secrets Manager directly:\n# GitHub Actions - name: Sync secrets to K8s run: | aws secretsmanager get-secret-value \\ --secret-id prod/db-password \\ --query SecretString \\ --output text | \\ kubectl create secret generic db-creds \\ --from-literal=password=$(cat) \\ --dry-run=client -o yaml | \\ kubectl apply -f - No secrets in GitHub Actions env vars either. Uses OIDC to authenticate to AWS.\nSealed Secrets (alternative approach) If you can\u0026rsquo;t use external secret management, Sealed Secrets is next best:\n# Install Sealed Secrets controller kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/controller.yaml # Install kubeseal CLI brew install kubeseal # Create sealed secret (encrypted, safe to commit) kubectl create secret generic mysecret \\ --from-literal=password=mypassword \\ --dry-run=client -o yaml | \\ kubeseal -o yaml \u0026gt; sealed-secret.yaml # Commit sealed-secret.yaml to git git add sealed-secret.yaml sealed-secret.yaml is encrypted with the cluster\u0026rsquo;s public key. Only the Sealed Secrets controller (running in-cluster) can decrypt it.\nWe use this for non-critical secrets like webhook URLs. Critical secrets (DB passwords, API keys) still go to AWS Secrets Manager.\nThe actual security model Developers never see production secrets - They\u0026rsquo;re stored in AWS Secrets Manager with restricted IAM access Secrets sync automatically - External Secrets Operator pulls them into K8s Secrets encrypted at rest - Both in AWS (KMS) and K8s (encryption config) Secrets encrypted in transit - TLS between everything Secrets audited - CloudTrail logs every access to AWS Secrets Manager Secrets rotated - Automatically every 30 days We also use:\nRBAC to limit who can read Secrets in K8s Pod Security Standards to prevent privilege escalation OPA Gatekeeper policies to block plaintext secrets in manifests What actually stopped the leaks Not technology. Code review policies.\nWe added a pre-commit hook:\n# .git/hooks/pre-commit #!/bin/bash if git diff --cached | grep -iE \u0026#34;password|secret|key.*=|token\u0026#34; | grep -v \u0026#34;secretKeyRef\u0026#34;; then echo \u0026#34;❌ Possible secret detected in commit!\u0026#34; echo \u0026#34;Use Kubernetes Secrets or External Secrets instead.\u0026#34; exit 1 fi And a CI check:\n# GitHub Actions - name: Scan for secrets uses: trufflesecurity/trufflehog@main with: path: ./ base: main head: HEAD TruffleHog scans commits for patterns that look like secrets (AWS keys, JWT tokens, private keys). Fails the build if it finds any.\nWe also enabled GitHub\u0026rsquo;s secret scanning and got alerts when we pushed known patterns.\nThe $2,400 lesson AWS detected unusual activity within hours. Their abuse team emailed us. We:\nRotated all potentially exposed credentials Killed the rogue EC2 instances Enabled CloudTrail logging everywhere Set up billing alerts Requested a bill adjustment (AWS forgave $1,800 as a one-time courtesy) Total actual cost: $600 + a week of security hardening work.\nCould\u0026rsquo;ve been worse. We learned about External Secrets, IRSA, secret encryption, and the importance of secret scanning before someone used our keys to access customer data instead of just mining crypto.\nThe real fix wasn\u0026rsquo;t technical. It was making secrets management a team priority and building guardrails that prevent accidents before they happen.\n","permalink":"https://pixcave.com/posts/kubernetes-secrets-security/","summary":"\u003cp\u003eFound our AWS access keys in a public GitHub repo last month. Fun times. Here\u0026rsquo;s how it happened and what we actually did to prevent it.\u003c/p\u003e\n\u003ch2 id=\"how-we-leaked-them\"\u003eHow we leaked them\u003c/h2\u003e\n\u003cp\u003eDeveloper needed to add an API key to a Kubernetes service. Did this:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# deployment.yaml - DON\u0026#39;T DO THIS\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eapiVersion\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eapps/v1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ekind\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDeployment\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003emetadata\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eapi-service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003espec\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003espec\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003econtainers\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eapi\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eenv\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eAWS_ACCESS_KEY\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003evalue\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;AKIAIOSFODNN7EXAMPLE\u0026#34;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 🚨 Plaintext in git!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eAWS_SECRET_KEY\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003evalue\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCommitted it. Pushed it. Public repo. Keys were active for 6 hours before AWS alerted us to unusual activity.\u003c/p\u003e","title":"Kubernetes Secrets: How We Leaked API Keys (And Fixed It)"},{"content":"GraphQL makes it stupidly easy to write queries that murder your database. Our homepage was hitting the database 2,031 times per page load. Yeah.\nHere\u0026rsquo;s how we got it down to 3 queries without changing the API.\nThe query that looked innocent query Homepage { posts { id title author { id name avatar } comments { id text author { name } } } } Looks fine. Perfectly reasonable GraphQL query. Returns 10 posts with their authors and comments.\nThe database explosion Our naive resolver implementation:\nconst resolvers = { Query: { posts: () =\u0026gt; db.query(\u0026#34;SELECT * FROM posts LIMIT 10\u0026#34;) }, Post: { author: (post) =\u0026gt; db.query(\u0026#34;SELECT * FROM users WHERE id = ?\u0026#34;, [post.author_id]), comments: (post) =\u0026gt; db.query(\u0026#34;SELECT * FROM comments WHERE post_id = ?\u0026#34;, [post.id]) }, Comment: { author: (comment) =\u0026gt; db.query(\u0026#34;SELECT * FROM users WHERE id = ?\u0026#34;, [comment.author_id]) } }; For 10 posts with average 20 comments each:\n1 query: SELECT * FROM posts LIMIT 10 10 queries: SELECT * FROM users WHERE id = ? (one per post author) 10 queries: SELECT * FROM comments WHERE post_id = ? (one per post) 200 queries: SELECT * FROM users WHERE id = ? (one per comment author) --- 221 total queries And that\u0026rsquo;s the N+1 problem. Actually it\u0026rsquo;s more like N+N*M+1. Brutal.\nPage load time: 3.2 seconds. Most of it waiting on database queries.\nDataLoader: The solution everyone mentions Facebook\u0026rsquo;s DataLoader batches and caches database calls:\nimport DataLoader from \u0026#39;dataloader\u0026#39;; const userLoader = new DataLoader(async (userIds) =\u0026gt; { const users = await db.query( \u0026#34;SELECT * FROM users WHERE id IN (?)\u0026#34;, [userIds] ); // Return users in same order as requested IDs return userIds.map(id =\u0026gt; users.find(u =\u0026gt; u.id === id)); }); const resolvers = { Post: { author: (post) =\u0026gt; userLoader.load(post.author_id) // Batched! }, Comment: { author: (comment) =\u0026gt; userLoader.load(comment.author_id) // Batched! } }; Now instead of 210 individual SELECT * FROM users WHERE id = ? queries, we get:\n-- One batched query for all unique user IDs SELECT * FROM users WHERE id IN (1, 2, 3, 4, 5, 6, 7...) Down to 13 queries total. Big improvement.\nPage load: 800ms.\nBut DataLoader has gotchas DataLoader caches per request. This bit us:\n// User updates their profile await db.query(\u0026#34;UPDATE users SET name = ? WHERE id = ?\u0026#34;, [\u0026#34;New Name\u0026#34;, userId]); // Immediately query for that user const user = await userLoader.load(userId); // Still returns old name! Cached from earlier in the request Had to manually clear the cache:\nawait db.query(\u0026#34;UPDATE users SET name = ? WHERE id = ?\u0026#34;, [\u0026#34;New Name\u0026#34;, userId]); userLoader.clear(userId); // Clear cache for this ID Easy to forget. Caused subtle bugs where data appeared stale.\nThe better solution: SQL joins Why are we even doing separate queries? SQL can join this data:\nconst Query = { posts: async () =\u0026gt; { const postsWithAuthors = await db.query(` SELECT p.*, u.id as author_id, u.name as author_name, u.avatar as author_avatar FROM posts p LEFT JOIN users u ON p.author_id = u.id LIMIT 10 `); return postsWithAuthors.map(row =\u0026gt; ({ id: row.id, title: row.title, author: { id: row.author_id, name: row.author_name, avatar: row.author_avatar } })); } }; One query instead of 11. But comments are still separate queries. Can we join those too?\nconst Query = { posts: async () =\u0026gt; { const rows = await db.query(` SELECT p.*, author.id as author_id, author.name as author_name, c.id as comment_id, c.text as comment_text, commenter.id as commenter_id, commenter.name as commenter_name FROM posts p LEFT JOIN users author ON p.author_id = author.id LEFT JOIN comments c ON c.post_id = p.id LEFT JOIN users commenter ON c.author_id = commenter.id WHERE p.id IN (SELECT id FROM posts LIMIT 10) `); // Group rows by post const postsMap = new Map(); rows.forEach(row =\u0026gt; { if (!postsMap.has(row.id)) { postsMap.set(row.id, { id: row.id, title: row.title, author: { id: row.author_id, name: row.author_name }, comments: [] }); } if (row.comment_id) { postsMap.get(row.id).comments.push({ id: row.comment_id, text: row.comment_text, author: { id: row.commenter_id, name: row.commenter_name } }); } }); return Array.from(postsMap.values()); } }; Down to 1 query. But this approach has problems:\nCartesian explosion - 10 posts × 20 comments = 200 rows returned for 10 posts Overfetching - We\u0026rsquo;re returning all comment data even if the client only asked for comments { id } Maintenance nightmare - Add a field to the schema? Update the SQL join and mapping logic The actual solution: Prisma Switched to Prisma ORM which handles this automatically:\nconst posts = await prisma.post.findMany({ take: 10, include: { author: true, comments: { include: { author: true } } } }); Prisma generates this SQL:\n-- Query 1: Get posts with authors SELECT p.*, u.* FROM posts p LEFT JOIN users u ON p.author_id = u.id LIMIT 10; -- Query 2: Get all comments for these posts SELECT c.* FROM comments c WHERE c.post_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); -- Query 3: Get all comment authors SELECT u.* FROM users u WHERE u.id IN (SELECT DISTINCT author_id FROM comments WHERE post_id IN (...)); Three queries. No N+1 problem. No manual batching. Prisma figures it out.\nHandling dynamic field selection What if the client doesn\u0026rsquo;t request comments?\nquery Homepage { posts { id title # No comments field! } } Prisma still fetches comments. Overfetching.\nSolution: Use GraphQL field info:\nimport { GraphQLResolveInfo } from \u0026#39;graphql\u0026#39;; import graphqlFields from \u0026#39;graphql-fields\u0026#39;; const Query = { posts: async (parent, args, context, info: GraphQLResolveInfo) =\u0026gt; { const fields = graphqlFields(info); return prisma.post.findMany({ take: 10, include: { author: \u0026#39;author\u0026#39; in fields, comments: \u0026#39;comments\u0026#39; in fields ? { include: { author: fields.comments?.author !== undefined } } : false } }); } }; Now Prisma only fetches data the client actually requested. No overfetching.\nQuery complexity limits Even with perfect resolvers, clients can still abuse GraphQL:\nquery Evil { posts { comments { author { posts { comments { author { posts { # Infinite nesting! } } } } } } } } This crashes our server. Solution: Query complexity limits.\nimport { createComplexityLimitRule } from \u0026#39;graphql-validation-complexity\u0026#39;; const server = new ApolloServer({ typeDefs, resolvers, validationRules: [ createComplexityLimitRule(1000, { onCost: (cost) =\u0026gt; console.log(\u0026#39;Query cost:\u0026#39;, cost), scalarCost: 1, objectCost: 2, listFactor: 10 }) ] }); Complexity calculation:\nEach scalar field: 1 point Each object field: 2 points Each list: × 10 multiplier Our posts query with authors and comments: ~250 points. Acceptable.\nThe evil nested query: ~50,000 points. Rejected.\nQuery depth limits Also limit nesting depth:\nimport depthLimit from \u0026#39;graphql-depth-limit\u0026#39;; const server = new ApolloServer({ validationRules: [ depthLimit(5) // Max 5 levels of nesting ] }); Now the infinite nesting query fails validation before execution.\nMonitoring query performance Added Apollo Studio integration:\nconst server = new ApolloServer({ apollo: { key: process.env.APOLLO_KEY, graphRef: process.env.APOLLO_GRAPH_REF }, plugins: [ ApolloServerPluginUsageReporting({ sendVariableValues: { all: true }, sendHeaders: { all: true } }) ] }); Now we see:\nWhich queries are slowest Which resolvers take the most time Query distribution (how often each query is called) Discovered our searchPosts query was called 1000× more than expected. Client was polling it every second. Fixed by adding a subscription instead.\nCaching with Redis For expensive queries that don\u0026rsquo;t change often:\nimport { createRedisCache } from \u0026#39;@apollo/utils.keyvaluecache\u0026#39;; const server = new ApolloServer({ cache: createRedisCache({ host: \u0026#39;redis\u0026#39;, port: 6379 }) }); const Query = { popularPosts: async (_, __, { cache }) =\u0026gt; { const cacheKey = \u0026#39;popularPosts\u0026#39;; const cached = await cache.get(cacheKey); if (cached) { return JSON.parse(cached); } const posts = await prisma.post.findMany({ orderBy: { views: \u0026#39;desc\u0026#39; }, take: 10 }); await cache.set(cacheKey, JSON.stringify(posts), { ttl: 300 }); // 5min return posts; } }; Popular posts change slowly. Cache for 5 minutes, save database load.\nWhat actually fixed our performance Prisma - Handles N+1 automatically with smart query batching Field selection - Only fetch data the client requested Query limits - Prevent abusive queries from reaching resolvers Monitoring - Apollo Studio showed us which queries needed optimization Caching - Redis for expensive, cacheable queries Current stats:\nHomepage: 3 database queries (down from 2,031) Page load: 180ms (down from 3.2s) Database CPU: 5% (down from 85%) The key insight: GraphQL\u0026rsquo;s flexibility is great for clients, terrible for databases. You need an ORM or dataloading layer that understands GraphQL\u0026rsquo;s execution model and can batch queries intelligently.\nDataLoader works but requires manual setup for every relationship. Prisma just handles it. We stopped fighting the framework and let the tools do the work.\nAlso turns out some of our slow queries were slow because of missing indexes, not N+1 problems. But that\u0026rsquo;s a different article.\n","permalink":"https://pixcave.com/posts/graphql-n-plus-one-problem/","summary":"\u003cp\u003eGraphQL makes it stupidly easy to write queries that murder your database. Our homepage was hitting the database 2,031 times per page load. Yeah.\u003c/p\u003e\n\u003cp\u003eHere\u0026rsquo;s how we got it down to 3 queries without changing the API.\u003c/p\u003e\n\u003ch2 id=\"the-query-that-looked-innocent\"\u003eThe query that looked innocent\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-graphql\" data-lang=\"graphql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003equery\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eHomepage\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  posts {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    title\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    author {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      name\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      avatar\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    comments {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      text\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      author {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        name\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLooks fine. Perfectly reasonable GraphQL query. Returns 10 posts with their authors and comments.\u003c/p\u003e","title":"GraphQL N+1 Problem: From 2000 Queries to 3"},{"content":"Docker has become the standard for containerization, but running containers in production requires following best practices for security, performance, and reliability. This guide covers essential practices for production Docker deployments.\nImage optimization Use multi-stage builds Reduce final image size by using multi-stage builds:\n# Stage 1: Build FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Runtime FROM node:18-alpine WORKDIR /app RUN addgroup -g 1001 -S nodejs \u0026amp;\u0026amp; \\ adduser -S nodejs -u 1001 COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules COPY --chown=nodejs:nodejs package*.json ./ USER nodejs EXPOSE 3000 CMD [\u0026#34;node\u0026#34;, \u0026#34;dist/index.js\u0026#34;] Use minimal base images Prefer Alpine or distroless images:\n# Bad: Full OS image FROM ubuntu:22.04 # Good: Minimal image FROM node:18-alpine # Better: Distroless (no shell, minimal attack surface) FROM gcr.io/distroless/nodejs18-debian11 Layer optimization Order Dockerfile instructions from least to most frequently changing:\n# Bad: Dependencies copied after code COPY . . RUN npm install # Good: Dependencies first (better caching) COPY package*.json ./ RUN npm ci --only=production COPY . . Remove unnecessary files Use .dockerignore to exclude files:\nnode_modules npm-debug.log .git .gitignore .env .nyc_output coverage .DS_Store *.md Security best practices Run as non-root user Never run containers as root:\n# Create non-root user RUN addgroup -g 1001 -S appgroup \u0026amp;\u0026amp; \\ adduser -S appuser -u 1001 -G appgroup # Switch to non-root user USER appuser Scan images for vulnerabilities # Use Trivy trivy image myapp:latest # Use Docker Scout docker scout quickview myapp:latest # In CI/CD - name: Scan image run: | docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \\ aquasec/trivy image myapp:latest Use specific image tags Avoid latest tag in production:\n# Bad FROM node:latest # Good FROM node:18.17.0-alpine Keep images updated Regularly update base images and dependencies:\n# Use specific versions FROM node:18.17.0-alpine # Update regularly # Check for security updates monthly Limit capabilities Drop unnecessary Linux capabilities:\n# docker-compose.yml services: app: cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Only what\u0026#39;s needed Use secrets management Never hardcode secrets:\n# Bad ENV DB_PASSWORD=secret123 # Good: Use Docker secrets or environment variables # Pass at runtime # Runtime docker run -e DB_PASSWORD=$(cat /path/to/secret) myapp Resource management Set resource limits Always set memory and CPU limits:\n# docker-compose.yml services: app: deploy: resources: limits: cpus: \u0026#39;1.0\u0026#39; memory: 512M reservations: cpus: \u0026#39;0.5\u0026#39; memory: 256M Health checks Implement proper health checks:\nHEALTHCHECK --interval=30s --timeout=3s --start-period=40s \\ CMD curl -f http://localhost:3000/health || exit 1 Or in docker-compose:\nhealthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;curl\u0026#34;, \u0026#34;-f\u0026#34;, \u0026#34;http://localhost:3000/health\u0026#34;] interval: 30s timeout: 10s retries: 3 start_period: 40s Logging and monitoring Use structured logging # Configure logging driver # In docker-compose.yml logging: driver: \u0026#34;json-file\u0026#34; options: max-size: \u0026#34;10m\u0026#34; max-file: \u0026#34;3\u0026#34; Centralize logs # Use logging driver for centralized logging logging: driver: \u0026#34;fluentd\u0026#34; options: fluentd-address: \u0026#34;localhost:24224\u0026#34; tag: \u0026#34;app.logs\u0026#34; Networking Use custom networks Isolate containers with custom networks:\n# Create network docker network create app-network # Connect containers docker run --network=app-network myapp Avoid host network mode # Bad: Exposes container to host network network_mode: \u0026#34;host\u0026#34; # Good: Use bridge network networks: - app-network Data persistence Use volumes for persistent data volumes: - app-data:/var/lib/app/data volumes: app-data: driver: local Avoid bind mounts in production # Development: OK volumes: - ./data:/app/data # Production: Use named volumes volumes: - app-data:/app/data Build optimization Leverage build cache # Order matters for cache efficiency # 1. Install dependencies (changes less frequently) COPY package*.json ./ RUN npm ci # 2. Copy source code (changes frequently) COPY . . RUN npm run build Use BuildKit Enable BuildKit for faster builds:\nexport DOCKER_BUILDKIT=1 docker build -t myapp . Or in Dockerfile:\n# syntax=docker/dockerfile:1.4 FROM node:18-alpine # ... rest of Dockerfile Production deployment Use orchestration For production, use orchestration tools:\nDocker Swarm: Built-in orchestration Kubernetes: Industry standard Nomad: HashiCorp\u0026rsquo;s orchestrator Implement restart policies restart_policy: condition: on-failure delay: 5s max_attempts: 3 window: 120s Use init containers For cleanup and initialization:\n# docker-compose.yml services: app: init: true # Uses tini as init system Monitoring and observability Expose metrics # Expose metrics endpoint EXPOSE 9090 # Application should expose /metrics endpoint Use labels Add metadata with labels:\nLABEL maintainer=\u0026#34;team@example.com\u0026#34; LABEL version=\u0026#34;1.0.0\u0026#34; LABEL description=\u0026#34;Production application\u0026#34; Best practices checklist Image optimization Use multi-stage builds Use minimal base images (Alpine/distroless) Optimize layer ordering Use .dockerignore Remove unnecessary files Security Run as non-root user Scan images for vulnerabilities Use specific image tags Keep images updated Limit capabilities Use secrets management Resource management Set memory limits Set CPU limits Implement health checks Configure restart policies Operations Use structured logging Centralize logs Use custom networks Use volumes for persistence Implement monitoring Conclusion Following Docker best practices is essential for production deployments. Focus on security, performance, and reliability. Regularly review and update your Docker configurations, scan for vulnerabilities, and monitor container health.\nRemember: Security and reliability should never be compromised for convenience. Take the time to implement these practices from the start.\n","permalink":"https://pixcave.com/posts/docker-production-best-practices-2024/","summary":"\u003cp\u003eDocker has become the standard for containerization, but running containers in production requires following best practices for security, performance, and reliability. This guide covers essential practices for production Docker deployments.\u003c/p\u003e\n\u003ch2 id=\"image-optimization\"\u003eImage optimization\u003c/h2\u003e\n\u003ch3 id=\"use-multi-stage-builds\"\u003eUse multi-stage builds\u003c/h3\u003e\n\u003cp\u003eReduce final image size by using multi-stage builds:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Stage 1: Build\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:18-alpine\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eAS\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003ebuilder\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eWORKDIR\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e/app\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e package*.json ./\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm ci\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm run build\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Stage 2: Runtime\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:18-alpine\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eWORKDIR\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e/app\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e addgroup -g \u003cspan style=\"color:#ae81ff\"\u003e1001\u003c/span\u003e -S nodejs \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e\u003c/span\u003e    adduser -S nodejs -u \u003cspan style=\"color:#ae81ff\"\u003e1001\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e --from\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebuilder --chown\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enodejs:nodejs /app/dist ./dist\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e --from\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebuilder --chown\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enodejs:nodejs /app/node_modules ./node_modules\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e --chown\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enodejs:nodejs package*.json ./\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eUSER\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enodejs\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eEXPOSE\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e3000\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCMD\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;node\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dist/index.js\u0026#34;\u003c/span\u003e]\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-minimal-base-images\"\u003eUse minimal base images\u003c/h3\u003e\n\u003cp\u003ePrefer Alpine or distroless images:\u003c/p\u003e","title":"Docker Production Best Practices: Security, Performance, and Reliability"},{"content":"Laravel remains one of the most popular PHP frameworks. Here are modern development practices for building scalable Laravel applications.\n1. Project Structure Recommended Structure app/ ├── Http/ │ ├── Controllers/ │ ├── Middleware/ │ ├── Requests/ │ └── Resources/ ├── Models/ ├── Services/ ├── Repositories/ ├── Events/ ├── Listeners/ └── Jobs/ 2. Eloquent Best Practices Model Relationships // User Model class User extends Model { public function posts() { return $this-\u0026gt;hasMany(Post::class); } public function profile() { return $this-\u0026gt;hasOne(Profile::class); } public function roles() { return $this-\u0026gt;belongsToMany(Role::class); } } Eager Loading // Bad: N+1 problem $users = User::all(); foreach ($users as $user) { echo $user-\u0026gt;posts-\u0026gt;count(); // Query for each user } // Good: Eager loading $users = User::with(\u0026#39;posts\u0026#39;)-\u0026gt;get(); foreach ($users as $user) { echo $user-\u0026gt;posts-\u0026gt;count(); // No additional queries } Query Scopes class Post extends Model { public function scopePublished($query) { return $query-\u0026gt;where(\u0026#39;status\u0026#39;, \u0026#39;published\u0026#39;); } public function scopeRecent($query) { return $query-\u0026gt;orderBy(\u0026#39;created_at\u0026#39;, \u0026#39;desc\u0026#39;); } } // Usage $posts = Post::published()-\u0026gt;recent()-\u0026gt;get(); 3. Service Layer Pattern Service Class class UserService { protected $userRepository; protected $emailService; public function __construct( UserRepository $userRepository, EmailService $emailService ) { $this-\u0026gt;userRepository = $userRepository; $this-\u0026gt;emailService = $emailService; } public function createUser(array $data): User { DB::beginTransaction(); try { $user = $this-\u0026gt;userRepository-\u0026gt;create($data); $this-\u0026gt;emailService-\u0026gt;sendWelcomeEmail($user); DB::commit(); return $user; } catch (\\Exception $e) { DB::rollBack(); throw $e; } } } 4. Form Requests Validation class CreateUserRequest extends FormRequest { public function rules(): array { return [ \u0026#39;name\u0026#39; =\u0026gt; [\u0026#39;required\u0026#39;, \u0026#39;string\u0026#39;, \u0026#39;max:255\u0026#39;], \u0026#39;email\u0026#39; =\u0026gt; [\u0026#39;required\u0026#39;, \u0026#39;email\u0026#39;, \u0026#39;unique:users,email\u0026#39;], \u0026#39;password\u0026#39; =\u0026gt; [\u0026#39;required\u0026#39;, \u0026#39;string\u0026#39;, \u0026#39;min:8\u0026#39;, \u0026#39;confirmed\u0026#39;], ]; } public function messages(): array { return [ \u0026#39;email.unique\u0026#39; =\u0026gt; \u0026#39;This email is already registered.\u0026#39;, \u0026#39;password.min\u0026#39; =\u0026gt; \u0026#39;Password must be at least 8 characters.\u0026#39;, ]; } } // Controller public function store(CreateUserRequest $request) { $user = $this-\u0026gt;userService-\u0026gt;createUser($request-\u0026gt;validated()); return new UserResource($user); } 5. API Resources Resource Transformation class UserResource extends JsonResource { public function toArray($request): array { return [ \u0026#39;id\u0026#39; =\u0026gt; $this-\u0026gt;id, \u0026#39;name\u0026#39; =\u0026gt; $this-\u0026gt;name, \u0026#39;email\u0026#39; =\u0026gt; $this-\u0026gt;email, \u0026#39;created_at\u0026#39; =\u0026gt; $this-\u0026gt;created_at-\u0026gt;toIso8601String(), \u0026#39;posts\u0026#39; =\u0026gt; PostResource::collection($this-\u0026gt;whenLoaded(\u0026#39;posts\u0026#39;)), ]; } } 6. Queues and Jobs Job Implementation class SendWelcomeEmail implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct( public User $user ) {} public function handle(EmailService $emailService): void { $emailService-\u0026gt;sendWelcomeEmail($this-\u0026gt;user); } public function failed(\\Throwable $exception): void { // Handle failure } } // Dispatch SendWelcomeEmail::dispatch($user); 7. Events and Listeners Event System // Event class UserRegistered { public function __construct( public User $user ) {} } // Listener class SendWelcomeEmail { public function handle(UserRegistered $event): void { Mail::to($event-\u0026gt;user-\u0026gt;email)-\u0026gt;send(new WelcomeMail($event-\u0026gt;user)); } } // Dispatch event(new UserRegistered($user)); 8. Caching Cache Implementation // Cache user $user = Cache::remember(\u0026#34;user.{$id}\u0026#34;, 3600, function () use ($id) { return User::find($id); }); // Cache tags Cache::tags([\u0026#39;users\u0026#39;, \u0026#39;posts\u0026#39;])-\u0026gt;put(\u0026#34;user.{$id}\u0026#34;, $user, 3600); // Clear cache Cache::tags([\u0026#39;users\u0026#39;])-\u0026gt;flush(); 9. Database Migrations Migration Best Practices Schema::create(\u0026#39;users\u0026#39;, function (Blueprint $table) { $table-\u0026gt;id(); $table-\u0026gt;string(\u0026#39;email\u0026#39;)-\u0026gt;unique(); $table-\u0026gt;string(\u0026#39;name\u0026#39;); $table-\u0026gt;timestamp(\u0026#39;email_verified_at\u0026#39;)-\u0026gt;nullable(); $table-\u0026gt;string(\u0026#39;password\u0026#39;); $table-\u0026gt;timestamps(); $table-\u0026gt;softDeletes(); $table-\u0026gt;index(\u0026#39;email\u0026#39;); }); 10. Testing Feature Tests class UserTest extends TestCase { use RefreshDatabase; public function test_can_create_user(): void { $response = $this-\u0026gt;postJson(\u0026#39;/api/users\u0026#39;, [ \u0026#39;name\u0026#39; =\u0026gt; \u0026#39;John Doe\u0026#39;, \u0026#39;email\u0026#39; =\u0026gt; \u0026#39;john@example.com\u0026#39;, \u0026#39;password\u0026#39; =\u0026gt; \u0026#39;password123\u0026#39;, \u0026#39;password_confirmation\u0026#39; =\u0026gt; \u0026#39;password123\u0026#39;, ]); $response-\u0026gt;assertStatus(201) -\u0026gt;assertJsonStructure([ \u0026#39;data\u0026#39; =\u0026gt; [ \u0026#39;id\u0026#39;, \u0026#39;name\u0026#39;, \u0026#39;email\u0026#39;, ] ]); $this-\u0026gt;assertDatabaseHas(\u0026#39;users\u0026#39;, [ \u0026#39;email\u0026#39; =\u0026gt; \u0026#39;john@example.com\u0026#39;, ]); } } Best Practices Use Service Layer for business logic Form Requests for validation API Resources for data transformation Queues for long-running tasks Events for decoupled actions Eager Loading to avoid N+1 queries Caching for performance Write Tests for critical paths Conclusion Laravel provides powerful tools for building modern applications. Follow these practices to create maintainable, scalable Laravel applications! 🚀\n","permalink":"https://pixcave.com/posts/php-laravel-modern-development/","summary":"\u003cp\u003eLaravel remains one of the most popular PHP frameworks. Here are modern development practices for building scalable Laravel applications.\u003c/p\u003e\n\u003ch2 id=\"1-project-structure\"\u003e1. Project Structure\u003c/h2\u003e\n\u003ch3 id=\"recommended-structure\"\u003eRecommended Structure\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eapp/\n├── Http/\n│   ├── Controllers/\n│   ├── Middleware/\n│   ├── Requests/\n│   └── Resources/\n├── Models/\n├── Services/\n├── Repositories/\n├── Events/\n├── Listeners/\n└── Jobs/\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"2-eloquent-best-practices\"\u003e2. Eloquent Best Practices\u003c/h2\u003e\n\u003ch3 id=\"model-relationships\"\u003eModel Relationships\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// User Model\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eModel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ehasMany\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ePost\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprofile\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ehasOne\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eProfile\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eroles\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ebelongsToMany\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eRole\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"eager-loading\"\u003eEager Loading\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: N+1 problem\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$users \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eall\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eforeach\u003c/span\u003e ($users \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e $user) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e $user\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// Query for each user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Eager loading\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$users \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ewith\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;posts\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eforeach\u003c/span\u003e ($users \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e $user) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e $user\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// No additional queries\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"query-scopes\"\u003eQuery Scopes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePost\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eModel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003escopePublished\u003c/span\u003e($query)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $query\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ewhere\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;status\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;published\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003escopeRecent\u003c/span\u003e($query)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $query\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eorderBy\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;created_at\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;desc\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Usage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$posts \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePost\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003epublished\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erecent\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-service-layer-pattern\"\u003e3. Service Layer Pattern\u003c/h2\u003e\n\u003ch3 id=\"service-class\"\u003eService Class\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprotected\u003c/span\u003e $userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprotected\u003c/span\u003e $emailService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__construct\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eUserRepository\u003c/span\u003e $userRepository,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eEmailService\u003c/span\u003e $emailService\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euserRepository\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eemailService\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $emailService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e $data)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eDB\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ebeginTransaction\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euserRepository\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e($data);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eemailService\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esendWelcomeEmail\u003c/span\u003e($user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eDB\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecommit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $user;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003e\\Exception\u003c/span\u003e $e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eDB\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erollBack\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e $e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-form-requests\"\u003e4. Form Requests\u003c/h2\u003e\n\u003ch3 id=\"validation\"\u003eValidation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCreateUserRequest\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eFormRequest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erules\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;required\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;string\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;max:255\u0026#39;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;required\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;unique:users,email\u0026#39;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;required\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;string\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;min:8\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;confirmed\u0026#39;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emessages\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email.unique\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;This email is already registered.\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password.min\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Password must be at least 8 characters.\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Controller\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estore\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eCreateUserRequest\u003c/span\u003e $request)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euserService\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e($request\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalidated\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserResource\u003c/span\u003e($user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-api-resources\"\u003e5. API Resources\u003c/h2\u003e\n\u003ch3 id=\"resource-transformation\"\u003eResource Transformation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserResource\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eJsonResource\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etoArray\u003c/span\u003e($request)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;created_at\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecreated_at\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etoIso8601String\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;posts\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePostResource\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecollection\u003c/span\u003e($this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ewhenLoaded\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;posts\u0026#39;\u003c/span\u003e)),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-queues-and-jobs\"\u003e6. Queues and Jobs\u003c/h2\u003e\n\u003ch3 id=\"job-implementation\"\u003eJob Implementation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSendWelcomeEmail\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eShouldQueue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDispatchable\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eInteractsWithQueue\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eQueueable\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eSerializesModels\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__construct\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e $user\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eEmailService\u003c/span\u003e $emailService)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evoid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $emailService\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esendWelcomeEmail\u003c/span\u003e($this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efailed\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e\\Throwable\u003c/span\u003e $exception)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evoid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Handle failure\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Dispatch\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSendWelcomeEmail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edispatch\u003c/span\u003e($user);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-events-and-listeners\"\u003e7. Events and Listeners\u003c/h2\u003e\n\u003ch3 id=\"event-system\"\u003eEvent System\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Event\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRegistered\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__construct\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e $user\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Listener\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSendWelcomeEmail\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eUserRegistered\u003c/span\u003e $event)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evoid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eMail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eto\u003c/span\u003e($event\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWelcomeMail\u003c/span\u003e($event\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Dispatch\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRegistered\u003c/span\u003e($user));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"8-caching\"\u003e8. Caching\u003c/h2\u003e\n\u003ch3 id=\"cache-implementation\"\u003eCache Implementation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Cache user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCache\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eremember\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user.\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003e$id\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () \u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e ($id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e($id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Cache tags\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eCache\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etags\u003c/span\u003e([\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;posts\u0026#39;\u003c/span\u003e])\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eput\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user.\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003e$id\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, $user, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Clear cache\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eCache\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etags\u003c/span\u003e([\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e])\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eflush\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"9-database-migrations\"\u003e9. Database Migrations\u003c/h2\u003e\n\u003ch3 id=\"migration-best-practices\"\u003eMigration Best Practices\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eSchema\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eBlueprint\u003c/span\u003e $table) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003estring\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eunique\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003estring\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etimestamp\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email_verified_at\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003enullable\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003estring\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etimestamps\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esoftDeletes\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $table\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"10-testing\"\u003e10. Testing\u003c/h2\u003e\n\u003ch3 id=\"feature-tests\"\u003eFeature Tests\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserTest\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eTestCase\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRefreshDatabase\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest_can_create_user\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evoid\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $response \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003epostJson\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/users\u0026#39;\u003c/span\u003e, [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;John Doe\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;john@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password_confirmation\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $response\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eassertStatus\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e201\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eassertJsonStructure\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;data\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;id\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;name\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eassertDatabaseHas\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e, [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;email\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;john@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse Service Layer\u003c/strong\u003e for business logic\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eForm Requests\u003c/strong\u003e for validation\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAPI Resources\u003c/strong\u003e for data transformation\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eQueues\u003c/strong\u003e for long-running tasks\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEvents\u003c/strong\u003e for decoupled actions\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEager Loading\u003c/strong\u003e to avoid N+1 queries\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCaching\u003c/strong\u003e for performance\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWrite Tests\u003c/strong\u003e for critical paths\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eLaravel provides powerful tools for building modern applications. Follow these practices to create maintainable, scalable Laravel applications! 🚀\u003c/p\u003e","title":"Laravel Modern Development: Best Practices and Patterns"},{"content":"Go\u0026rsquo;s concurrency model is one of its strongest features. Here\u0026rsquo;s how to effectively use goroutines, channels, and concurrency patterns.\nGoroutines Basic Usage // Simple goroutine go func() { fmt.Println(\u0026#34;Running in goroutine\u0026#34;) }() // With function go processData(data) WaitGroup import \u0026#34;sync\u0026#34; var wg sync.WaitGroup func main() { for i := 0; i \u0026lt; 10; i++ { wg.Add(1) go func(id int) { defer wg.Done() processItem(id) }(i) } wg.Wait() // Wait for all goroutines } Channels Basic Channel Operations // Unbuffered channel ch := make(chan int) // Send ch \u0026lt;- 42 // Receive value := \u0026lt;-ch // Close close(ch) Buffered Channels // Buffered channel (capacity 10) ch := make(chan int, 10) // Non-blocking send if buffer not full ch \u0026lt;- 1 ch \u0026lt;- 2 Channel Directions // Send-only channel func sendOnly(ch chan\u0026lt;- int) { ch \u0026lt;- 42 } // Receive-only channel func receiveOnly(ch \u0026lt;-chan int) { value := \u0026lt;-ch } // Bidirectional (default) func bidirectional(ch chan int) { ch \u0026lt;- 42 value := \u0026lt;-ch } Common Patterns Worker Pool func workerPool(jobs \u0026lt;-chan int, results chan\u0026lt;- int, numWorkers int) { var wg sync.WaitGroup for i := 0; i \u0026lt; numWorkers; i++ { wg.Add(1) go func() { defer wg.Done() for job := range jobs { result := processJob(job) results \u0026lt;- result } }() } wg.Wait() close(results) } Fan-Out, Fan-In // Fan-out: Distribute work func fanOut(input \u0026lt;-chan int, outputs []chan int) { for value := range input { for _, output := range outputs { output \u0026lt;- value } } for _, output := range outputs { close(output) } } // Fan-in: Combine results func fanIn(inputs []\u0026lt;-chan int) \u0026lt;-chan int { output := make(chan int) var wg sync.WaitGroup for _, input := range inputs { wg.Add(1) go func(ch \u0026lt;-chan int) { defer wg.Done() for value := range ch { output \u0026lt;- value } }(input) } go func() { wg.Wait() close(output) }() return output } Pipeline Pattern func pipeline(input \u0026lt;-chan int) \u0026lt;-chan int { stage1 := make(chan int) stage2 := make(chan int) // Stage 1 go func() { defer close(stage1) for value := range input { stage1 \u0026lt;- value * 2 } }() // Stage 2 go func() { defer close(stage2) for value := range stage1 { stage2 \u0026lt;- value + 1 } }() return stage2 } Context for Cancellation Using Context import \u0026#34;context\u0026#34; func processWithContext(ctx context.Context, data []int) error { for _, item := range data { select { case \u0026lt;-ctx.Done(): return ctx.Err() default: processItem(item) } } return nil } // Usage ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() err := processWithContext(ctx, data) Context with Timeout ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result, err := fetchData(ctx) Select Statement Non-Blocking Operations select { case value := \u0026lt;-ch1: // Handle value from ch1 case value := \u0026lt;-ch2: // Handle value from ch2 case ch3 \u0026lt;- 42: // Successfully sent to ch3 default: // No channel ready } Timeout Pattern select { case result := \u0026lt;-ch: return result case \u0026lt;-time.After(5 * time.Second): return errors.New(\u0026#34;timeout\u0026#34;) } Mutex and RWMutex Protecting Shared State type SafeCounter struct { mu sync.Mutex value int } func (c *SafeCounter) Increment() { c.mu.Lock() defer c.mu.Unlock() c.value++ } func (c *SafeCounter) Value() int { c.mu.Lock() defer c.mu.Unlock() return c.value } Read-Write Mutex type SafeMap struct { mu sync.RWMutex data map[string]int } func (m *SafeMap) Get(key string) int { m.mu.RLock() defer m.mu.RUnlock() return m.data[key] } func (m *SafeMap) Set(key string, value int) { m.mu.Lock() defer m.mu.Unlock() m.data[key] = value } Best Practices 1. Always Use defer for Cleanup // Good func process() { mu.Lock() defer mu.Unlock() // Process } // Bad func process() { mu.Lock() // Process mu.Unlock() // Might not execute if panic } 2. Avoid Goroutine Leaks // Good: Use context for cancellation func worker(ctx context.Context) { for { select { case \u0026lt;-ctx.Done(): return default: // Work } } } // Bad: Goroutine runs forever func worker() { for { // Work forever } } 3. Close Channels Properly // Good: Close channel when done func producer(ch chan int) { defer close(ch) for i := 0; i \u0026lt; 10; i++ { ch \u0026lt;- i } } Common Pitfalls 1. Race Conditions // Bad: Race condition var counter int func increment() { counter++ // Not thread-safe } // Good: Use mutex var ( counter int mu sync.Mutex ) func increment() { mu.Lock() defer mu.Unlock() counter++ } 2. Closing Closed Channel // Bad: Panic if channel already closed close(ch) close(ch) // Panic! // Good: Check or use sync.Once var once sync.Once once.Do(func() { close(ch) }) Performance Tips 1. Use Buffered Channels // For known capacity ch := make(chan int, 100) 2. Limit Goroutine Count // Use worker pool instead of unlimited goroutines const maxWorkers = 10 semaphore := make(chan struct{}, maxWorkers) 3. Profile Your Code import _ \u0026#34;net/http/pprof\u0026#34; // Add to main go func() { log.Println(http.ListenAndServe(\u0026#34;localhost:6060\u0026#34;, nil)) }() Conclusion Go\u0026rsquo;s concurrency model provides:\nGoroutines: Lightweight threads Channels: Safe communication Select: Multiplexing Context: Cancellation and timeouts Key principles:\nDon\u0026rsquo;t communicate by sharing memory; share memory by communicating Use channels for communication Use mutexes only when necessary Always handle context cancellation Avoid goroutine leaks Master these patterns to write efficient, concurrent Go programs! 🚀\n","permalink":"https://pixcave.com/posts/go-concurrency-patterns/","summary":"\u003cp\u003eGo\u0026rsquo;s concurrency model is one of its strongest features. Here\u0026rsquo;s how to effectively use goroutines, channels, and concurrency patterns.\u003c/p\u003e\n\u003ch2 id=\"goroutines\"\u003eGoroutines\u003c/h2\u003e\n\u003ch3 id=\"basic-usage\"\u003eBasic Usage\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Simple goroutine\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efmt\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ePrintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Running in goroutine\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// With function\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessData\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"waitgroup\"\u003eWaitGroup\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sync\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWaitGroup\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u0026lt; \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eAdd\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDone\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eprocessItem\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }(\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWait\u003c/span\u003e() \u003cspan style=\"color:#75715e\"\u003e// Wait for all goroutines\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"channels\"\u003eChannels\u003c/h2\u003e\n\u003ch3 id=\"basic-channel-operations\"\u003eBasic Channel Operations\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Unbuffered channel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Send\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e42\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Receive\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Close\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclose(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"buffered-channels\"\u003eBuffered Channels\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Buffered channel (capacity 10)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Non-blocking send if buffer not full\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"channel-directions\"\u003eChannel Directions\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Send-only channel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esendOnly\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e42\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Receive-only channel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereceiveOnly\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bidirectional (default)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebidirectional\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e42\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-patterns\"\u003eCommon Patterns\u003c/h2\u003e\n\u003ch3 id=\"worker-pool\"\u003eWorker Pool\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eworkerPool\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ejobs\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eresults\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enumWorkers\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWaitGroup\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u0026lt; \u003cspan style=\"color:#a6e22e\"\u003enumWorkers\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eAdd\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDone\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejob\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejobs\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessJob\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ejob\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eresults\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWait\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    close(\u003cspan style=\"color:#a6e22e\"\u003eresults\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"fan-out-fan-in\"\u003eFan-Out, Fan-In\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Fan-out: Distribute work\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efanOut\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eoutputs\u003c/span\u003e []\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoutputs\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoutputs\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        close(\u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Fan-in: Combine results\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efanIn\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einputs\u003c/span\u003e []\u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWaitGroup\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einputs\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eAdd\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDone\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }(\u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWait\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        close(\u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoutput\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"pipeline-pattern\"\u003ePipeline Pattern\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epipeline\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003estage1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003estage2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Stage 1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e close(\u003cspan style=\"color:#a6e22e\"\u003estage1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003estage1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Stage 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e close(\u003cspan style=\"color:#a6e22e\"\u003estage2\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estage1\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003estage2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estage2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"context-for-cancellation\"\u003eContext for Cancellation\u003c/h2\u003e\n\u003ch3 id=\"using-context\"\u003eUsing Context\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;context\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessWithContext\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eContext\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e []\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eerror\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eitem\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erange\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eselect\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDone\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eErr\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eprocessItem\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eitem\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enil\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Usage\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecancel\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWithTimeout\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eBackground\u003c/span\u003e(), \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eSecond\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecancel\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessWithContext\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"context-with-timeout\"\u003eContext with Timeout\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecancel\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eWithTimeout\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eBackground\u003c/span\u003e(), \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eSecond\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecancel\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"select-statement\"\u003eSelect Statement\u003c/h2\u003e\n\u003ch3 id=\"non-blocking-operations\"\u003eNon-Blocking Operations\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eselect\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech1\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Handle value from ch1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech2\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Handle value from ch2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ech3\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e42\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Successfully sent to ch3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// No channel ready\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"timeout-pattern\"\u003eTimeout Pattern\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eselect\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eAfter\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eSecond\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerrors\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eNew\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;timeout\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"mutex-and-rwmutex\"\u003eMutex and RWMutex\u003c/h2\u003e\n\u003ch3 id=\"protecting-shared-state\"\u003eProtecting Shared State\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSafeCounter\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e    \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eMutex\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSafeCounter\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003eIncrement\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSafeCounter\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003eValue\u003c/span\u003e() \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"read-write-mutex\"\u003eRead-Write Mutex\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSafeMap\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eRWMutex\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emap\u003c/span\u003e[\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e]\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSafeMap\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003eGet\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eRLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eRUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSafeMap\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003eSet\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e] = \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003ch3 id=\"1-always-use-defer-for-cleanup\"\u003e1. Always Use defer for Cleanup\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Process\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Process\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e() \u003cspan style=\"color:#75715e\"\u003e// Might not execute if panic\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-avoid-goroutine-leaks\"\u003e2. Avoid Goroutine Leaks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use context for cancellation\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eContext\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eselect\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ectx\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDone\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// Work\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Goroutine runs forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Work forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-close-channels-properly\"\u003e3. Close Channels Properly\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Close channel when done\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eproducer\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e close(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u0026lt; \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;-\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-pitfalls\"\u003eCommon Pitfalls\u003c/h2\u003e\n\u003ch3 id=\"1-race-conditions\"\u003e1. Race Conditions\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Race condition\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecounter\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecounter\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// Not thread-safe\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use mutex\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecounter\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e      \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eMutex\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eLock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefer\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUnlock\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecounter\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-closing-closed-channel\"\u003e2. Closing Closed Channel\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Panic if channel already closed\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclose(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclose(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e// Panic!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Check or use sync.Once\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonce\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esync\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eOnce\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eonce\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eDo\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() { close(\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e) })\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"performance-tips\"\u003ePerformance Tips\u003c/h2\u003e\n\u003ch3 id=\"1-use-buffered-channels\"\u003e1. Use Buffered Channels\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// For known capacity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ech\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-limit-goroutine-count\"\u003e2. Limit Goroutine Count\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use worker pool instead of unlimited goroutines\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emaxWorkers\u003c/span\u003e = \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esemaphore\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e make(\u003cspan style=\"color:#66d9ef\"\u003echan\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e{}, \u003cspan style=\"color:#a6e22e\"\u003emaxWorkers\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-profile-your-code\"\u003e3. Profile Your Code\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-go\" data-lang=\"go\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;net/http/pprof\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Add to main\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ego\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ePrintln\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ehttp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eListenAndServe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;localhost:6060\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003enil\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eGo\u0026rsquo;s concurrency model provides:\u003c/p\u003e","title":"Go Concurrency Patterns: Goroutines, Channels, and Best Practices"},{"content":"Spring Boot is the most popular Java framework for building enterprise applications. Here are best practices for building production-ready Spring Boot applications.\n1. Project Structure Recommended Structure src/ ├── main/ │ ├── java/ │ │ └── com/example/ │ │ ├── Application.java │ │ ├── config/ │ │ ├── controller/ │ │ ├── service/ │ │ ├── repository/ │ │ ├── model/ │ │ └── dto/ │ └── resources/ │ ├── application.yml │ └── application-prod.yml └── test/ 2. Configuration Management Use YAML for Configuration # application.yml spring: datasource: url: jdbc:postgresql://localhost:5432/mydb username: ${DB_USERNAME} password: ${DB_PASSWORD} jpa: hibernate: ddl-auto: validate show-sql: false properties: hibernate: format_sql: true server: port: 8080 error: include-message: always include-stacktrace: on_param Profile-Based Configuration # application-dev.yml spring: datasource: url: jdbc:h2:mem:testdb jpa: show-sql: true # application-prod.yml spring: datasource: url: ${DATABASE_URL} jpa: show-sql: false 3. Dependency Injection Constructor Injection // Good: Constructor injection @Service public class UserService { private final UserRepository userRepository; private final EmailService emailService; public UserService(UserRepository userRepository, EmailService emailService) { this.userRepository = userRepository; this.emailService = emailService; } } // Bad: Field injection @Service public class UserService { @Autowired private UserRepository userRepository; } 4. Exception Handling Global Exception Handler @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity\u0026lt;ErrorResponse\u0026gt; handleNotFound( ResourceNotFoundException ex) { ErrorResponse error = new ErrorResponse( HttpStatus.NOT_FOUND.value(), ex.getMessage() ); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity\u0026lt;ErrorResponse\u0026gt; handleValidation( MethodArgumentNotValidException ex) { Map\u0026lt;String, String\u0026gt; errors = new HashMap\u0026lt;\u0026gt;(); ex.getBindingResult().getFieldErrors().forEach(error -\u0026gt; errors.put(error.getField(), error.getDefaultMessage()) ); ErrorResponse error = new ErrorResponse( HttpStatus.BAD_REQUEST.value(), \u0026#34;Validation failed\u0026#34;, errors ); return ResponseEntity.badRequest().body(error); } } 5. REST API Design Controller Best Practices @RestController @RequestMapping(\u0026#34;/api/v1/users\u0026#34;) @Validated public class UserController { private final UserService userService; @GetMapping public ResponseEntity\u0026lt;List\u0026lt;UserDTO\u0026gt;\u0026gt; getAllUsers( @RequestParam(defaultValue = \u0026#34;0\u0026#34;) int page, @RequestParam(defaultValue = \u0026#34;20\u0026#34;) int size) { List\u0026lt;UserDTO\u0026gt; users = userService.getAllUsers(page, size); return ResponseEntity.ok(users); } @GetMapping(\u0026#34;/{id}\u0026#34;) public ResponseEntity\u0026lt;UserDTO\u0026gt; getUser(@PathVariable Long id) { UserDTO user = userService.getUserById(id); return ResponseEntity.ok(user); } @PostMapping public ResponseEntity\u0026lt;UserDTO\u0026gt; createUser( @Valid @RequestBody CreateUserRequest request) { UserDTO user = userService.createUser(request); return ResponseEntity.status(HttpStatus.CREATED).body(user); } @PutMapping(\u0026#34;/{id}\u0026#34;) public ResponseEntity\u0026lt;UserDTO\u0026gt; updateUser( @PathVariable Long id, @Valid @RequestBody UpdateUserRequest request) { UserDTO user = userService.updateUser(id, request); return ResponseEntity.ok(user); } @DeleteMapping(\u0026#34;/{id}\u0026#34;) public ResponseEntity\u0026lt;Void\u0026gt; deleteUser(@PathVariable Long id) { userService.deleteUser(id); return ResponseEntity.noContent().build(); } } 6. Service Layer Service Implementation @Service @Transactional public class UserService { private final UserRepository userRepository; private final UserMapper userMapper; public UserDTO getUserById(Long id) { User user = userRepository.findById(id) .orElseThrow(() -\u0026gt; new ResourceNotFoundException( \u0026#34;User not found with id: \u0026#34; + id)); return userMapper.toDTO(user); } public UserDTO createUser(CreateUserRequest request) { if (userRepository.existsByEmail(request.getEmail())) { throw new DuplicateResourceException( \u0026#34;Email already exists\u0026#34;); } User user = userMapper.toEntity(request); user = userRepository.save(user); return userMapper.toDTO(user); } } 7. Repository Layer JPA Repository @Repository public interface UserRepository extends JpaRepository\u0026lt;User, Long\u0026gt; { Optional\u0026lt;User\u0026gt; findByEmail(String email); boolean existsByEmail(String email); @Query(\u0026#34;SELECT u FROM User u WHERE u.status = :status\u0026#34;) List\u0026lt;User\u0026gt; findByStatus(@Param(\u0026#34;status\u0026#34;) UserStatus status); @Modifying @Query(\u0026#34;UPDATE User u SET u.status = :status WHERE u.id = :id\u0026#34;) int updateStatus(@Param(\u0026#34;id\u0026#34;) Long id, @Param(\u0026#34;status\u0026#34;) UserStatus status); } 8. Entity Design JPA Entity @Entity @Table(name = \u0026#34;users\u0026#34;) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, unique = true) private String email; @Column(nullable = false) private String name; @Enumerated(EnumType.STRING) private UserStatus status; @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; @Version private Long version; // Getters and setters } 9. Validation DTO Validation public class CreateUserRequest { @NotBlank(message = \u0026#34;Email is required\u0026#34;) @Email(message = \u0026#34;Invalid email format\u0026#34;) private String email; @NotBlank(message = \u0026#34;Name is required\u0026#34;) @Size(min = 2, max = 100, message = \u0026#34;Name must be between 2 and 100 characters\u0026#34;) private String name; @Min(value = 18, message = \u0026#34;Age must be at least 18\u0026#34;) @Max(value = 120, message = \u0026#34;Age must be at most 120\u0026#34;) private Integer age; // Getters and setters } 10. Security Spring Security Configuration @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests(auth -\u0026gt; auth .requestMatchers(\u0026#34;/api/public/**\u0026#34;).permitAll() .requestMatchers(\u0026#34;/api/admin/**\u0026#34;).hasRole(\u0026#34;ADMIN\u0026#34;) .anyRequest().authenticated() ) .sessionManagement(session -\u0026gt; session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .oauth2ResourceServer(oauth2 -\u0026gt; oauth2 .jwt(jwt -\u0026gt; jwt.decoder(jwtDecoder())) ); return http.build(); } } 11. Testing Unit Tests @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @InjectMocks private UserService userService; @Test void shouldCreateUser() { // Given CreateUserRequest request = new CreateUserRequest(); request.setEmail(\u0026#34;test@example.com\u0026#34;); request.setName(\u0026#34;Test User\u0026#34;); User savedUser = new User(); savedUser.setId(1L); savedUser.setEmail(request.getEmail()); when(userRepository.existsByEmail(request.getEmail())).thenReturn(false); when(userRepository.save(any(User.class))).thenReturn(savedUser); // When UserDTO result = userService.createUser(request); // Then assertThat(result.getId()).isEqualTo(1L); assertThat(result.getEmail()).isEqualTo(\u0026#34;test@example.com\u0026#34;); } } Integration Tests @SpringBootTest @AutoConfigureMockMvc class UserControllerIntegrationTest { @Autowired private MockMvc mockMvc; @Autowired private UserRepository userRepository; @Test void shouldCreateUser() throws Exception { CreateUserRequest request = new CreateUserRequest(); request.setEmail(\u0026#34;test@example.com\u0026#34;); request.setName(\u0026#34;Test User\u0026#34;); mockMvc.perform(post(\u0026#34;/api/v1/users\u0026#34;) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) .andExpect(jsonPath(\u0026#34;$.email\u0026#34;).value(\u0026#34;test@example.com\u0026#34;)); } } 12. Performance Optimization Connection Pooling spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 Caching @Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager(\u0026#34;users\u0026#34;, \u0026#34;posts\u0026#34;); } } // Usage @Service public class UserService { @Cacheable(value = \u0026#34;users\u0026#34;, key = \u0026#34;#id\u0026#34;) public UserDTO getUserById(Long id) { return userRepository.findById(id) .map(userMapper::toDTO) .orElseThrow(); } @CacheEvict(value = \u0026#34;users\u0026#34;, key = \u0026#34;#id\u0026#34;) public void deleteUser(Long id) { userRepository.deleteById(id); } } 13. Monitoring and Logging Actuator Endpoints management: endpoints: web: exposure: include: health,info,metrics,prometheus endpoint: health: show-details: when-authorized Logging Configuration logging: level: root: INFO com.example: DEBUG pattern: console: \u0026#34;%d{yyyy-MM-dd HH:mm:ss} - %msg%n\u0026#34; file: \u0026#34;%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n\u0026#34; file: name: logs/application.log max-size: 10MB max-history: 30 Best Practices Summary Use constructor injection for dependencies Implement global exception handling Validate all inputs with Bean Validation Use DTOs to separate API from domain models Implement proper logging and monitoring Use profiles for environment-specific config Write comprehensive tests Optimize database queries Implement caching where appropriate Follow RESTful conventions Conclusion Spring Boot best practices help you build:\nMaintainable applications Scalable systems Secure APIs Testable code Production-ready services Follow these practices to build robust Spring Boot applications! ☕\n","permalink":"https://pixcave.com/posts/java-spring-boot-best-practices/","summary":"\u003cp\u003eSpring Boot is the most popular Java framework for building enterprise applications. Here are best practices for building production-ready Spring Boot applications.\u003c/p\u003e\n\u003ch2 id=\"1-project-structure\"\u003e1. Project Structure\u003c/h2\u003e\n\u003ch3 id=\"recommended-structure\"\u003eRecommended Structure\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esrc/\n├── main/\n│   ├── java/\n│   │   └── com/example/\n│   │       ├── Application.java\n│   │       ├── config/\n│   │       ├── controller/\n│   │       ├── service/\n│   │       ├── repository/\n│   │       ├── model/\n│   │       └── dto/\n│   └── resources/\n│       ├── application.yml\n│       └── application-prod.yml\n└── test/\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"2-configuration-management\"\u003e2. Configuration Management\u003c/h2\u003e\n\u003ch3 id=\"use-yaml-for-configuration\"\u003eUse YAML for Configuration\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# application.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003espring\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edatasource\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejdbc:postgresql://localhost:5432/mydb\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eusername\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${DB_USERNAME}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003epassword\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${DB_PASSWORD}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejpa\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ehibernate\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eddl-auto\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003evalidate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eshow-sql\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eproperties\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003ehibernate\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003eformat_sql\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eserver\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eport\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e8080\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eerror\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003einclude-message\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ealways\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003einclude-stacktrace\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eon_param\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"profile-based-configuration\"\u003eProfile-Based Configuration\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# application-dev.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003espring\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edatasource\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ejdbc:h2:mem:testdb\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejpa\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eshow-sql\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# application-prod.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003espring\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edatasource\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e${DATABASE_URL}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003ejpa\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eshow-sql\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-dependency-injection\"\u003e3. Dependency Injection\u003c/h2\u003e\n\u003ch3 id=\"constructor-injection\"\u003eConstructor Injection\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Constructor injection\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e UserRepository userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e EmailService emailService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e(UserRepository userRepository, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      EmailService emailService) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euserRepository\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemailService\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e emailService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Field injection\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Autowired\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e UserRepository userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-exception-handling\"\u003e4. Exception Handling\u003c/h2\u003e\n\u003ch3 id=\"global-exception-handler\"\u003eGlobal Exception Handler\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RestControllerAdvice\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eGlobalExceptionHandler\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@ExceptionHandler\u003c/span\u003e(ResourceNotFoundException.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eErrorResponse\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleNotFound\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ResourceNotFoundException ex) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ErrorResponse error \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ErrorResponse(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            HttpStatus.\u003cspan style=\"color:#a6e22e\"\u003eNOT_FOUND\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ex.\u003cspan style=\"color:#a6e22e\"\u003egetMessage\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e(HttpStatus.\u003cspan style=\"color:#a6e22e\"\u003eNOT_FOUND\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e(error);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@ExceptionHandler\u003c/span\u003e(MethodArgumentNotValidException.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eErrorResponse\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleValidation\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            MethodArgumentNotValidException ex) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Map\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString, String\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e errors \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e HashMap\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ex.\u003cspan style=\"color:#a6e22e\"\u003egetBindingResult\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003egetFieldErrors\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eforEach\u003c/span\u003e(error \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            errors.\u003cspan style=\"color:#a6e22e\"\u003eput\u003c/span\u003e(error.\u003cspan style=\"color:#a6e22e\"\u003egetField\u003c/span\u003e(), error.\u003cspan style=\"color:#a6e22e\"\u003egetDefaultMessage\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ErrorResponse error \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ErrorResponse(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            HttpStatus.\u003cspan style=\"color:#a6e22e\"\u003eBAD_REQUEST\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Validation failed\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            errors\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003ebadRequest\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e(error);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-rest-api-design\"\u003e5. REST API Design\u003c/h2\u003e\n\u003ch3 id=\"controller-best-practices\"\u003eController Best Practices\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RestController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RequestMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/api/v1/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Validated\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserController\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e UserService userService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUserDTO\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetAllUsers\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@RequestParam\u003c/span\u003e(defaultValue \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0\u0026#34;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e page,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@RequestParam\u003c/span\u003e(defaultValue \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;20\u0026#34;\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e size) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUserDTO\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e users \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003egetAllUsers\u003c/span\u003e(page, size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003eok\u003c/span\u003e(users);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUserDTO\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        UserDTO user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003egetUserById\u003c/span\u003e(id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003eok\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@PostMapping\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUserDTO\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@Valid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e CreateUserRequest request) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        UserDTO user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(request);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e(HttpStatus.\u003cspan style=\"color:#a6e22e\"\u003eCREATED\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@PutMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUserDTO\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eupdateUser\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e Long id,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@Valid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e UpdateUserRequest request) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        UserDTO user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003eupdateUser\u003c/span\u003e(id, request);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003eok\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@DeleteMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eVoid\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edeleteUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        userService.\u003cspan style=\"color:#a6e22e\"\u003edeleteUser\u003c/span\u003e(id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003enoContent\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-service-layer\"\u003e6. Service Layer\u003c/h2\u003e\n\u003ch3 id=\"service-implementation\"\u003eService Implementation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Transactional\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e UserRepository userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e UserMapper userMapper;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e UserDTO \u003cspan style=\"color:#a6e22e\"\u003egetUserById\u003c/span\u003e(Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        User user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userRepository.\u003cspan style=\"color:#a6e22e\"\u003efindById\u003c/span\u003e(id)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eorElseThrow\u003c/span\u003e(() \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ResourceNotFoundException(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;User not found with id: \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e id));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userMapper.\u003cspan style=\"color:#a6e22e\"\u003etoDTO\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e UserDTO \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(CreateUserRequest request) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (userRepository.\u003cspan style=\"color:#a6e22e\"\u003eexistsByEmail\u003c/span\u003e(request.\u003cspan style=\"color:#a6e22e\"\u003egetEmail\u003c/span\u003e())) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e DuplicateResourceException(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Email already exists\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        User user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userMapper.\u003cspan style=\"color:#a6e22e\"\u003etoEntity\u003c/span\u003e(request);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userMapper.\u003cspan style=\"color:#a6e22e\"\u003etoDTO\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-repository-layer\"\u003e7. Repository Layer\u003c/h2\u003e\n\u003ch3 id=\"jpa-repository\"\u003eJPA Repository\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Repository\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRepository\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e JpaRepository\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser, Long\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Optional\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindByEmail\u003c/span\u003e(String email);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eboolean\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexistsByEmail\u003c/span\u003e(String email);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Query\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;SELECT u FROM User u WHERE u.status = :status\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindByStatus\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@Param\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;status\u0026#34;\u003c/span\u003e) UserStatus status);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Modifying\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Query\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UPDATE User u SET u.status = :status WHERE u.id = :id\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eupdateStatus\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@Param\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e) Long id, \u003cspan style=\"color:#a6e22e\"\u003e@Param\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;status\u0026#34;\u003c/span\u003e) UserStatus status);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"8-entity-design\"\u003e8. Entity Design\u003c/h2\u003e\n\u003ch3 id=\"jpa-entity\"\u003eJPA Entity\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Table\u003c/span\u003e(name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Id\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GeneratedValue\u003c/span\u003e(strategy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e GenerationType.\u003cspan style=\"color:#a6e22e\"\u003eIDENTITY\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Long id;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Column\u003c/span\u003e(nullable \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e, unique \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String email;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Column\u003c/span\u003e(nullable \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Enumerated\u003c/span\u003e(EnumType.\u003cspan style=\"color:#a6e22e\"\u003eSTRING\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e UserStatus status;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@CreatedDate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e LocalDateTime createdAt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@LastModifiedDate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e LocalDateTime updatedAt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Version\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Long version;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Getters and setters\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"9-validation\"\u003e9. Validation\u003c/h2\u003e\n\u003ch3 id=\"dto-validation\"\u003eDTO Validation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCreateUserRequest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotBlank\u003c/span\u003e(message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Email is required\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Email\u003c/span\u003e(message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid email format\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String email;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotBlank\u003c/span\u003e(message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Name is required\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Size\u003c/span\u003e(min \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 2, max \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 100, message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Name must be between 2 and 100 characters\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Min\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 18, message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Age must be at least 18\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Max\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 120, message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Age must be at most 120\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Integer age;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Getters and setters\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"10-security\"\u003e10. Security\u003c/h2\u003e\n\u003ch3 id=\"spring-security-configuration\"\u003eSpring Security Configuration\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Configuration\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@EnableWebSecurity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSecurityConfig\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Bean\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e SecurityFilterChain \u003cspan style=\"color:#a6e22e\"\u003efilterChain\u003c/span\u003e(HttpSecurity http) \u003cspan style=\"color:#66d9ef\"\u003ethrows\u003c/span\u003e Exception {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        http\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003ecsrf\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003edisable\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eauthorizeHttpRequests\u003c/span\u003e(auth \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e auth\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003erequestMatchers\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/api/public/**\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003epermitAll\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003erequestMatchers\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/api/admin/**\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ehasRole\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ADMIN\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003eanyRequest\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eauthenticated\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003esessionManagement\u003c/span\u003e(session \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e session\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003esessionCreationPolicy\u003c/span\u003e(SessionCreationPolicy.\u003cspan style=\"color:#a6e22e\"\u003eSTATELESS\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eoauth2ResourceServer\u003c/span\u003e(oauth2 \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e oauth2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003ejwt\u003c/span\u003e(jwt \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e jwt.\u003cspan style=\"color:#a6e22e\"\u003edecoder\u003c/span\u003e(jwtDecoder()))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e http.\u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"11-testing\"\u003e11. Testing\u003c/h2\u003e\n\u003ch3 id=\"unit-tests\"\u003eUnit Tests\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@ExtendWith\u003c/span\u003e(MockitoExtension.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserServiceTest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Mock\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e UserRepository userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@InjectMocks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e UserService userService;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Test\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshouldCreateUser\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Given\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        CreateUserRequest request \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e CreateUserRequest();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        request.\u003cspan style=\"color:#a6e22e\"\u003esetEmail\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test@example.com\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        request.\u003cspan style=\"color:#a6e22e\"\u003esetName\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Test User\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        User savedUser \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e User();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        savedUser.\u003cspan style=\"color:#a6e22e\"\u003esetId\u003c/span\u003e(1L);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        savedUser.\u003cspan style=\"color:#a6e22e\"\u003esetEmail\u003c/span\u003e(request.\u003cspan style=\"color:#a6e22e\"\u003egetEmail\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        when(userRepository.\u003cspan style=\"color:#a6e22e\"\u003eexistsByEmail\u003c/span\u003e(request.\u003cspan style=\"color:#a6e22e\"\u003egetEmail\u003c/span\u003e())).\u003cspan style=\"color:#a6e22e\"\u003ethenReturn\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        when(userRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(any(User.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e))).\u003cspan style=\"color:#a6e22e\"\u003ethenReturn\u003c/span\u003e(savedUser);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// When\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        UserDTO result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(request);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Then\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        assertThat(result.\u003cspan style=\"color:#a6e22e\"\u003egetId\u003c/span\u003e()).\u003cspan style=\"color:#a6e22e\"\u003eisEqualTo\u003c/span\u003e(1L);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        assertThat(result.\u003cspan style=\"color:#a6e22e\"\u003egetEmail\u003c/span\u003e()).\u003cspan style=\"color:#a6e22e\"\u003eisEqualTo\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test@example.com\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"integration-tests\"\u003eIntegration Tests\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@SpringBootTest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@AutoConfigureMockMvc\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserControllerIntegrationTest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Autowired\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e MockMvc mockMvc;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Autowired\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e UserRepository userRepository;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Test\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshouldCreateUser\u003c/span\u003e() \u003cspan style=\"color:#66d9ef\"\u003ethrows\u003c/span\u003e Exception {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        CreateUserRequest request \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e CreateUserRequest();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        request.\u003cspan style=\"color:#a6e22e\"\u003esetEmail\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test@example.com\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        request.\u003cspan style=\"color:#a6e22e\"\u003esetName\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Test User\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        mockMvc.\u003cspan style=\"color:#a6e22e\"\u003eperform\u003c/span\u003e(post(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/api/v1/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003econtentType\u003c/span\u003e(MediaType.\u003cspan style=\"color:#a6e22e\"\u003eAPPLICATION_JSON\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                .\u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e(objectMapper.\u003cspan style=\"color:#a6e22e\"\u003ewriteValueAsString\u003c/span\u003e(request)))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eandExpect\u003c/span\u003e(status().\u003cspan style=\"color:#a6e22e\"\u003eisCreated\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eandExpect\u003c/span\u003e(jsonPath(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;$.email\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test@example.com\u0026#34;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"12-performance-optimization\"\u003e12. Performance Optimization\u003c/h2\u003e\n\u003ch3 id=\"connection-pooling\"\u003eConnection Pooling\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003espring\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003edatasource\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ehikari\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003emaximum-pool-size\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eminimum-idle\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003econnection-timeout\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e30000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eidle-timeout\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e600000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003emax-lifetime\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e1800000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"caching\"\u003eCaching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Configuration\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@EnableCaching\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCacheConfig\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Bean\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e CacheManager \u003cspan style=\"color:#a6e22e\"\u003ecacheManager\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ConcurrentMapCacheManager(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;posts\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Usage\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Cacheable\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e, key \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#id\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e UserDTO \u003cspan style=\"color:#a6e22e\"\u003egetUserById\u003c/span\u003e(Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userRepository.\u003cspan style=\"color:#a6e22e\"\u003efindById\u003c/span\u003e(id)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(userMapper::toDTO)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eorElseThrow\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@CacheEvict\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e, key \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#id\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edeleteUser\u003c/span\u003e(Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        userRepository.\u003cspan style=\"color:#a6e22e\"\u003edeleteById\u003c/span\u003e(id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"13-monitoring-and-logging\"\u003e13. Monitoring and Logging\u003c/h2\u003e\n\u003ch3 id=\"actuator-endpoints\"\u003eActuator Endpoints\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003emanagement\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eendpoints\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eweb\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eexposure\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003einclude\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ehealth,info,metrics,prometheus\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eendpoint\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ehealth\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eshow-details\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003ewhen-authorized\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"logging-configuration\"\u003eLogging Configuration\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003elogging\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003elevel\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eroot\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eINFO\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ecom.example\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eDEBUG\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003epattern\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003econsole\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%d{yyyy-MM-dd HH:mm:ss} - %msg%n\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efile\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003efile\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003elogs/application.log\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003emax-size\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e10MB\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003emax-history\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e30\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices-summary\"\u003eBest Practices Summary\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse constructor injection\u003c/strong\u003e for dependencies\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement global exception handling\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eValidate all inputs\u003c/strong\u003e with Bean Validation\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse DTOs\u003c/strong\u003e to separate API from domain models\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement proper logging\u003c/strong\u003e and monitoring\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse profiles\u003c/strong\u003e for environment-specific config\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWrite comprehensive tests\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOptimize database queries\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement caching\u003c/strong\u003e where appropriate\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFollow RESTful conventions\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSpring Boot best practices help you build:\u003c/p\u003e","title":"Spring Boot Best Practices: Building Production-Ready Applications"},{"content":"Asynchronous programming is at the heart of Node.js. Here are practical strategies to master async operations.\nUnderstanding Async Patterns Callbacks // Traditional callback pattern function readFile(callback) { fs.readFile(\u0026#39;file.txt\u0026#39;, \u0026#39;utf8\u0026#39;, (err, data) =\u0026gt; { if (err) return callback(err); callback(null, data); }); } Promises // Promise-based function readFile() { return new Promise((resolve, reject) =\u0026gt; { fs.readFile(\u0026#39;file.txt\u0026#39;, \u0026#39;utf8\u0026#39;, (err, data) =\u0026gt; { if (err) reject(err); else resolve(data); }); }); } Async/Await // Modern async/await async function readFile() { try { const data = await fs.promises.readFile(\u0026#39;file.txt\u0026#39;, \u0026#39;utf8\u0026#39;); return data; } catch (err) { throw err; } } Common Patterns Sequential Execution // Execute operations one after another async function sequential() { const user = await getUser(userId); const profile = await getProfile(user.id); const posts = await getPosts(user.id); return { user, profile, posts }; } Parallel Execution // Execute operations in parallel async function parallel() { const [user, profile, posts] = await Promise.all([ getUser(userId), getProfile(userId), getPosts(userId) ]); return { user, profile, posts }; } Race Conditions // Get first resolved promise async function race() { const result = await Promise.race([ fetchFromAPI1(), fetchFromAPI2(), timeout(5000) // Fallback ]); return result; } Error Handling Try-Catch with Async/Await async function handleErrors() { try { const data = await fetchData(); return data; } catch (error) { if (error.code === \u0026#39;ENOENT\u0026#39;) { // Handle file not found } else if (error.code === \u0026#39;ECONNREFUSED\u0026#39;) { // Handle connection refused } else { // Handle other errors } throw error; } } Promise Error Handling // Chain error handling fetchData() .then(data =\u0026gt; processData(data)) .catch(error =\u0026gt; { console.error(\u0026#39;Error:\u0026#39;, error); return fallbackData(); }) .finally(() =\u0026gt; { cleanup(); }); Advanced Patterns Retry Logic async function retry(fn, maxRetries = 3) { for (let i = 0; i \u0026lt; maxRetries; i++) { try { return await fn(); } catch (error) { if (i === maxRetries - 1) throw error; await sleep(1000 * (i + 1)); // Exponential backoff } } } Timeout Pattern function withTimeout(promise, ms) { return Promise.race([ promise, new Promise((_, reject) =\u0026gt; setTimeout(() =\u0026gt; reject(new Error(\u0026#39;Timeout\u0026#39;)), ms) ) ]); } // Usage const data = await withTimeout(fetchData(), 5000); Batch Processing async function processBatch(items, batchSize = 10) { for (let i = 0; i \u0026lt; items.length; i += batchSize) { const batch = items.slice(i, i + batchSize); await Promise.all(batch.map(item =\u0026gt; processItem(item))); } } Best Practices 1. Always Await Promises // Bad: Fire and forget asyncFunction(); // Unhandled promise // Good: Always await await asyncFunction(); 2. Use Promise.all for Independent Operations // Good: Parallel execution const [users, posts, comments] = await Promise.all([ getUsers(), getPosts(), getComments() ]); 3. Handle Rejections // Always handle promise rejections process.on(\u0026#39;unhandledRejection\u0026#39;, (reason, promise) =\u0026gt; { console.error(\u0026#39;Unhandled Rejection:\u0026#39;, reason); }); Conclusion Mastering async operations requires:\nUnderstanding different patterns Proper error handling Efficient execution strategies Best practices for performance Practice these patterns to write better Node.js code! 🎯\n","permalink":"https://pixcave.com/posts/mastering-async-operations-nodejs/","summary":"\u003cp\u003eAsynchronous programming is at the heart of Node.js. Here are practical strategies to master async operations.\u003c/p\u003e\n\u003ch2 id=\"understanding-async-patterns\"\u003eUnderstanding Async Patterns\u003c/h2\u003e\n\u003ch3 id=\"callbacks\"\u003eCallbacks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Traditional callback pattern\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;utf8\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"promises\"\u003ePromises\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Promise-based\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Promise((\u003cspan style=\"color:#a6e22e\"\u003eresolve\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ereject\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;utf8\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003ereject\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresolve\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"asyncawait\"\u003eAsync/Await\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Modern async/await\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;utf8\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-patterns\"\u003eCommon Patterns\u003c/h2\u003e\n\u003ch3 id=\"sequential-execution\"\u003eSequential Execution\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Execute operations one after another\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esequential\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprofile\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetProfile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eprofile\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"parallel-execution\"\u003eParallel Execution\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Execute operations in parallel\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eparallel\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eprofile\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003eall\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetProfile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eprofile\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"race-conditions\"\u003eRace Conditions\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Get first resolved promise\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erace\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003erace\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efetchFromAPI1\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efetchFromAPI2\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003etimeout\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5000\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e// Fallback\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"error-handling\"\u003eError Handling\u003c/h2\u003e\n\u003ch3 id=\"try-catch-with-asyncawait\"\u003eTry-Catch with Async/Await\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleErrors\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ENOENT\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e// Handle file not found\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ECONNREFUSED\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e// Handle connection refused\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e// Handle other errors\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"promise-error-handling\"\u003ePromise Error Handling\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Chain error handling\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  .\u003cspan style=\"color:#a6e22e\"\u003ethen\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eprocessData\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  .\u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Error:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efallbackData\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  .\u003cspan style=\"color:#66d9ef\"\u003efinally\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecleanup\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"advanced-patterns\"\u003eAdvanced Patterns\u003c/h2\u003e\n\u003ch3 id=\"retry-logic\"\u003eRetry Logic\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eretry\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003efn\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003emaxRetries\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emaxRetries\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efn\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emaxRetries\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)); \u003cspan style=\"color:#75715e\"\u003e// Exponential backoff\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"timeout-pattern\"\u003eTimeout Pattern\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewithTimeout\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003epromise\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ems\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003erace\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003epromise\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Promise((\u003cspan style=\"color:#a6e22e\"\u003e_\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ereject\u003c/span\u003e) =\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003esetTimeout\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ereject\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Error(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Timeout\u0026#39;\u003c/span\u003e)), \u003cspan style=\"color:#a6e22e\"\u003ems\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Usage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewithTimeout\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e(), \u003cspan style=\"color:#ae81ff\"\u003e5000\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"batch-processing\"\u003eBatch Processing\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessBatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ebatchSize\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebatchSize\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebatch\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebatchSize\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003eall\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ebatch\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eitem\u003c/span\u003e =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eprocessItem\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eitem\u003c/span\u003e)));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003ch3 id=\"1-always-await-promises\"\u003e1. Always Await Promises\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Fire and forget\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003easyncFunction\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// Unhandled promise\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Always await\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003easyncFunction\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-use-promiseall-for-independent-operations\"\u003e2. Use Promise.all for Independent Operations\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Parallel execution\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecomments\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003eall\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetUsers\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetComments\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-handle-rejections\"\u003e3. Handle Rejections\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always handle promise rejections\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;unhandledRejection\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003ereason\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003epromise\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Unhandled Rejection:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ereason\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMastering async operations requires:\u003c/p\u003e","title":"Mastering Asynchronous Operations in Node.js: Practical Strategies"},{"content":"Understanding Node.js architecture is crucial for building scalable applications. Let\u0026rsquo;s dive into the event loop, async operations, and how Node.js handles concurrency.\nThe Event Loop Node.js uses a single-threaded event loop to handle asynchronous operations efficiently.\nEvent Loop Phases // Simplified event loop phases ┌───────────────────────────┐ │ ┌─────────────────────┐ │ │ │ Timers │ │ // setTimeout, setInterval │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ │ Pending Callbacks │ │ // I/O callbacks │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ │ Idle, Prepare │ │ // Internal use │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ │ Poll │ │ // Fetch new I/O events │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ │ Check │ │ // setImmediate callbacks │ └─────────────────────┘ │ │ ┌─────────────────────┐ │ │ │ Close Callbacks │ │ // socket.on(\u0026#39;close\u0026#39;) │ └─────────────────────┘ │ └───────────────────────────┘ How It Works // Example: Understanding execution order console.log(\u0026#39;1\u0026#39;); setTimeout(() =\u0026gt; console.log(\u0026#39;2\u0026#39;), 0); Promise.resolve().then(() =\u0026gt; console.log(\u0026#39;3\u0026#39;)); console.log(\u0026#39;4\u0026#39;); // Output: 1, 4, 3, 2 // Why: // - Synchronous code runs first (1, 4) // - Microtasks (Promises) run before macrotasks (setTimeout) // - Event loop processes callbacks Asynchronous Operations Callbacks // Traditional callback fs.readFile(\u0026#39;file.txt\u0026#39;, (err, data) =\u0026gt; { if (err) { console.error(err); return; } console.log(data); }); Promises // Promise-based fs.promises.readFile(\u0026#39;file.txt\u0026#39;) .then(data =\u0026gt; console.log(data)) .catch(err =\u0026gt; console.error(err)); // Async/await async function readFile() { try { const data = await fs.promises.readFile(\u0026#39;file.txt\u0026#39;); console.log(data); } catch (err) { console.error(err); } } Event Emitters const EventEmitter = require(\u0026#39;events\u0026#39;); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on(\u0026#39;event\u0026#39;, (data) =\u0026gt; { console.log(\u0026#39;Event received:\u0026#39;, data); }); myEmitter.emit(\u0026#39;event\u0026#39;, \u0026#39;Hello World\u0026#39;); Concurrency Model Single-Threaded but Non-Blocking // Node.js handles I/O asynchronously const http = require(\u0026#39;http\u0026#39;); // This doesn\u0026#39;t block http.get(\u0026#39;http://example.com\u0026#39;, (res) =\u0026gt; { res.on(\u0026#39;data\u0026#39;, (chunk) =\u0026gt; { console.log(chunk); }); }); // This continues immediately console.log(\u0026#39;Request sent, continuing...\u0026#39;); Worker Threads for CPU-Intensive Tasks // For CPU-intensive operations const { Worker, isMainThread, parentPort } = require(\u0026#39;worker_threads\u0026#39;); if (isMainThread) { const worker = new Worker(__filename); worker.postMessage(\u0026#39;Start calculation\u0026#39;); worker.on(\u0026#39;message\u0026#39;, (result) =\u0026gt; { console.log(\u0026#39;Result:\u0026#39;, result); }); } else { parentPort.on(\u0026#39;message\u0026#39;, (msg) =\u0026gt; { // Heavy computation const result = performHeavyCalculation(); parentPort.postMessage(result); }); } Scaling Strategies Cluster Module const cluster = require(\u0026#39;cluster\u0026#39;); const os = require(\u0026#39;os\u0026#39;); if (cluster.isMaster) { const numWorkers = os.cpus().length; for (let i = 0; i \u0026lt; numWorkers; i++) { cluster.fork(); } cluster.on(\u0026#39;exit\u0026#39;, (worker) =\u0026gt; { console.log(`Worker ${worker.id} died`); cluster.fork(); // Restart worker }); } else { // Worker process require(\u0026#39;./server.js\u0026#39;); } Load Balancing // PM2 for process management // pm2 start app.js -i max // Or use nginx/HAProxy for load balancing Best Practices 1. Avoid Blocking the Event Loop // Bad: Blocks event loop function heavyComputation() { let result = 0; for (let i = 0; i \u0026lt; 10000000000; i++) { result += i; } return result; } // Good: Use worker threads or break into chunks function asyncHeavyComputation() { return new Promise((resolve) =\u0026gt; { setImmediate(() =\u0026gt; { // Process in chunks resolve(computeChunk()); }); }); } 2. Use Streams for Large Data // Bad: Loads entire file into memory const data = fs.readFileSync(\u0026#39;large-file.txt\u0026#39;); // Good: Stream processing const stream = fs.createReadStream(\u0026#39;large-file.txt\u0026#39;); stream.on(\u0026#39;data\u0026#39;, (chunk) =\u0026gt; { processChunk(chunk); }); 3. Handle Errors Properly // Always handle errors in async operations async function fetchData() { try { const data = await fetch(\u0026#39;http://api.example.com\u0026#39;); return data; } catch (error) { // Log and handle error console.error(\u0026#39;Fetch failed:\u0026#39;, error); throw error; } } Performance Tips 1. Connection Pooling // Database connection pooling const pool = mysql.createPool({ connectionLimit: 10, host: \u0026#39;localhost\u0026#39;, user: \u0026#39;user\u0026#39;, password: \u0026#39;password\u0026#39;, database: \u0026#39;mydb\u0026#39; }); 2. Caching // Use Redis for caching const redis = require(\u0026#39;redis\u0026#39;); const client = redis.createClient(); async function getCachedData(key) { const cached = await client.get(key); if (cached) return JSON.parse(cached); const data = await fetchData(); await client.setex(key, 3600, JSON.stringify(data)); return data; } 3. Compression // Enable gzip compression const compression = require(\u0026#39;compression\u0026#39;); app.use(compression()); Common Pitfalls 1. Callback Hell // Bad: Nested callbacks fs.readFile(\u0026#39;file1.txt\u0026#39;, (err, data1) =\u0026gt; { fs.readFile(\u0026#39;file2.txt\u0026#39;, (err, data2) =\u0026gt; { fs.readFile(\u0026#39;file3.txt\u0026#39;, (err, data3) =\u0026gt; { // Deep nesting }); }); }); // Good: Use async/await async function readFiles() { const [data1, data2, data3] = await Promise.all([ fs.promises.readFile(\u0026#39;file1.txt\u0026#39;), fs.promises.readFile(\u0026#39;file2.txt\u0026#39;), fs.promises.readFile(\u0026#39;file3.txt\u0026#39;) ]); } 2. Unhandled Promise Rejections // Always handle promise rejections process.on(\u0026#39;unhandledRejection\u0026#39;, (reason, promise) =\u0026gt; { console.error(\u0026#39;Unhandled Rejection:\u0026#39;, reason); // Log and handle }); Conclusion Node.js architecture is powerful because:\nEvent-driven: Handles many connections efficiently Non-blocking I/O: Doesn\u0026rsquo;t wait for operations Single-threaded: Simpler concurrency model Scalable: Can handle thousands of connections Key takeaways:\nUnderstand the event loop phases Use async/await for cleaner code Avoid blocking operations Use worker threads for CPU-intensive tasks Implement proper error handling Scale with clustering or load balancing Master these concepts to build high-performance Node.js applications! 🚀\n","permalink":"https://pixcave.com/posts/nodejs-event-loop-explained/","summary":"\u003cp\u003eUnderstanding Node.js architecture is crucial for building scalable applications. Let\u0026rsquo;s dive into the event loop, async operations, and how Node.js handles concurrency.\u003c/p\u003e\n\u003ch2 id=\"the-event-loop\"\u003eThe Event Loop\u003c/h2\u003e\n\u003cp\u003eNode.js uses a single-threaded event loop to handle asynchronous operations efficiently.\u003c/p\u003e\n\u003ch3 id=\"event-loop-phases\"\u003eEvent Loop Phases\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Simplified event loop phases\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌───────────────────────────┐\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003eTimers\u003c/span\u003e            \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// setTimeout, setInterval\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003ePending\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCallbacks\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// I/O callbacks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003eIdle\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ePrepare\u003c/span\u003e     \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// Internal use\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003ePoll\u003c/span\u003e              \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// Fetch new I/O events\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003eCheck\u003c/span\u003e             \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// setImmediate callbacks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e┌─────────────────────┐\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#a6e22e\"\u003eClose\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCallbacks\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// socket.on(\u0026#39;close\u0026#39;)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└─────────────────────┘\u003c/span\u003e  \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e│\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e└───────────────────────────┘\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"how-it-works\"\u003eHow It Works\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Example: Understanding execution order\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;1\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetTimeout\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2\u0026#39;\u003c/span\u003e), \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePromise.\u003cspan style=\"color:#a6e22e\"\u003eresolve\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ethen\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;3\u0026#39;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;4\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Output: 1, 4, 3, 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Why: \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// - Synchronous code runs first (1, 4)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// - Microtasks (Promises) run before macrotasks (setTimeout)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// - Event loop processes callbacks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"asynchronous-operations\"\u003eAsynchronous Operations\u003c/h2\u003e\n\u003ch3 id=\"callbacks\"\u003eCallbacks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Traditional callback\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"promises\"\u003ePromises\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Promise-based\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  .\u003cspan style=\"color:#a6e22e\"\u003ethen\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  .\u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Async/await\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file.txt\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"event-emitters\"\u003eEvent Emitters\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEventEmitter\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;events\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMyEmitter\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEventEmitter\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emyEmitter\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMyEmitter\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emyEmitter\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;event\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Event received:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emyEmitter\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;event\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Hello World\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"concurrency-model\"\u003eConcurrency Model\u003c/h2\u003e\n\u003ch3 id=\"single-threaded-but-non-blocking\"\u003eSingle-Threaded but Non-Blocking\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Node.js handles I/O asynchronously\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehttp\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;http\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This doesn\u0026#39;t block\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ehttp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;http://example.com\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;data\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003echunk\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003echunk\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This continues immediately\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Request sent, continuing...\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"worker-threads-for-cpu-intensive-tasks\"\u003eWorker Threads for CPU-Intensive Tasks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// For CPU-intensive operations\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eWorker\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eisMainThread\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eparentPort\u003c/span\u003e } \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;worker_threads\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eisMainThread\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWorker\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e__filename\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epostMessage\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Start calculation\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;message\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Result:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e} \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eparentPort\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;message\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003emsg\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Heavy computation\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eperformHeavyCalculation\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eparentPort\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epostMessage\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"scaling-strategies\"\u003eScaling Strategies\u003c/h2\u003e\n\u003ch3 id=\"cluster-module\"\u003eCluster Module\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecluster\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;cluster\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eos\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;os\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ecluster\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eisMaster\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003enumWorkers\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eos\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecpus\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003enumWorkers\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecluster\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efork\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecluster\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;exit\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`Worker \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eworker\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e died`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecluster\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efork\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// Restart worker\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e} \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// Worker process\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;./server.js\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"load-balancing\"\u003eLoad Balancing\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// PM2 for process management\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// pm2 start app.js -i max\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Or use nginx/HAProxy for load balancing\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003ch3 id=\"1-avoid-blocking-the-event-loop\"\u003e1. Avoid Blocking the Event Loop\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Blocks event loop\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eheavyComputation\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10000000000\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use worker threads or break into chunks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003easyncHeavyComputation\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Promise((\u003cspan style=\"color:#a6e22e\"\u003eresolve\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetImmediate\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e// Process in chunks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e      \u003cspan style=\"color:#a6e22e\"\u003eresolve\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecomputeChunk\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-use-streams-for-large-data\"\u003e2. Use Streams for Large Data\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Loads entire file into memory\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFileSync\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;large-file.txt\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Stream processing\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estream\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateReadStream\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;large-file.txt\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003estream\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;data\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003echunk\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eprocessChunk\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003echunk\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-handle-errors-properly\"\u003e3. Handle Errors Properly\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always handle errors in async operations\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetch\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;http://api.example.com\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  } \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Log and handle error\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Fetch failed:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"performance-tips\"\u003ePerformance Tips\u003c/h2\u003e\n\u003ch3 id=\"1-connection-pooling\"\u003e1. Connection Pooling\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Database connection pooling\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epool\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emysql\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreatePool\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econnectionLimit\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ehost\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;localhost\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;user\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edatabase\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;mydb\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-caching\"\u003e2. Caching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use Redis for caching\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;redis\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateClient\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetCachedData\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecached\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ecached\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eparse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecached\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetchData\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetex\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estringify\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-compression\"\u003e3. Compression\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Enable gzip compression\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecompression\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;compression\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecompression\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-pitfalls\"\u003eCommon Pitfalls\u003c/h2\u003e\n\u003ch3 id=\"1-callback-hell\"\u003e1. Callback Hell\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Nested callbacks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file1.txt\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata1\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file2.txt\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata2\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file3.txt\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata3\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e// Deep nesting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use async/await\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereadFiles\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003edata1\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata2\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e Promise.\u003cspan style=\"color:#a6e22e\"\u003eall\u003c/span\u003e([\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file1.txt\u0026#39;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file2.txt\u0026#39;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efs\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epromises\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;file3.txt\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-unhandled-promise-rejections\"\u003e2. Unhandled Promise Rejections\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always handle promise rejections\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;unhandledRejection\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003ereason\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003epromise\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Unhandled Rejection:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ereason\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// Log and handle\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eNode.js architecture is powerful because:\u003c/p\u003e","title":"Node.js Architecture Explained: Event Loop, Async Code, and Scaling"},{"content":"GraphQL and REST are both popular API design approaches. Here\u0026rsquo;s when to use each.\nREST API Overview REST (Representational State Transfer) uses HTTP methods to interact with resources.\nCharacteristics Resource-based: URLs represent resources HTTP methods: GET, POST, PUT, DELETE Stateless: Each request is independent Multiple endpoints: Different URLs for different resources Example GET /api/users GET /api/users/123 POST /api/users PUT /api/users/123 DELETE /api/users/123 GraphQL Overview GraphQL is a query language and runtime for APIs.\nCharacteristics Single endpoint: One endpoint for all operations Client-driven: Clients specify what data they need Strongly typed: Schema defines all types Flexible queries: Get exactly what you need Example # Query query { user(id: \u0026#34;123\u0026#34;) { name email posts { title content } } } # Mutation mutation { createUser(name: \u0026#34;John\u0026#34;, email: \u0026#34;john@example.com\u0026#34;) { id name } } Key Differences 1. Data Fetching REST:\n# Multiple requests GET /api/users/123 GET /api/users/123/posts GET /api/users/123/followers GraphQL:\n# Single request query { user(id: \u0026#34;123\u0026#34;) { name posts { title } followers { name } } } 2. Over-fetching and Under-fetching REST:\nOver-fetching: Get more data than needed Under-fetching: Need multiple requests GraphQL:\nNo over-fetching: Get exactly what you need No under-fetching: Get all data in one request 3. Versioning REST:\nGET /api/v1/users GET /api/v2/users GraphQL:\n# Add new fields without breaking type User { id: ID! name: String! email: String! phone: String # New field, optional } When to Use REST Use REST When: Simple CRUD operations\nStandard create, read, update, delete No complex relationships Caching is important\nHTTP caching works well CDN integration File uploads\nREST handles file uploads easily GraphQL is more complex Simple data requirements\nFixed data structure No need for flexible queries Team familiarity\nTeam knows REST well Existing REST infrastructure REST Example // Express.js REST API app.get(\u0026#39;/api/users/:id\u0026#39;, async (req, res) =\u0026gt; { const user = await db.getUser(req.params.id); res.json(user); }); app.post(\u0026#39;/api/users\u0026#39;, async (req, res) =\u0026gt; { const user = await db.createUser(req.body); res.status(201).json(user); }); When to Use GraphQL Use GraphQL When: Complex data relationships\nMultiple related resources Nested data structures Mobile applications\nReduce over-fetching Save bandwidth Rapid frontend development\nFrontend changes don\u0026rsquo;t require backend changes Flexible queries Multiple clients\nWeb, mobile, desktop apps Different data requirements Real-time updates\nSubscriptions for live data WebSocket support GraphQL Example // Apollo Server const typeDefs = gql` type User { id: ID! name: String! email: String! posts: [Post!]! } type Query { user(id: ID!): User users: [User!]! } type Mutation { createUser(name: String!, email: String!): User! } `; const resolvers = { Query: { user: (_, { id }) =\u0026gt; db.getUser(id), users: () =\u0026gt; db.getUsers(), }, Mutation: { createUser: (_, { name, email }) =\u0026gt; db.createUser({ name, email }), }, }; Hybrid Approach You can use both:\n// REST for simple operations GET /api/users POST /api/users // GraphQL for complex queries POST /graphql { query: { user(id: \u0026#34;123\u0026#34;) { name posts { title } } } } Performance Considerations REST Caching: HTTP caching works well CDN: Easy to cache at edge Simple: Less overhead GraphQL Query complexity: Can be expensive N+1 problem: Need data loaders Caching: More complex to implement Tools and Libraries REST Express.js: Node.js framework Django REST: Python framework Spring Boot: Java framework FastAPI: Python framework GraphQL Apollo Server: Node.js GraphQL server GraphQL.js: Reference implementation Graphene: Python GraphQL library Sangria: Scala GraphQL library Migration Strategy From REST to GraphQL Start with queries: Add GraphQL for read operations Keep REST for writes: Gradually migrate mutations Coexist: Run both in parallel Deprecate REST: Once GraphQL is stable Conclusion Choose REST if:\nSimple CRUD operations Caching is critical Team is familiar with REST Standard HTTP patterns work Choose GraphQL if:\nComplex data relationships Multiple clients with different needs Mobile-first approach Rapid frontend iteration You can also use both:\nREST for simple operations GraphQL for complex queries Best of both worlds Remember: The best API is the one that:\nServes your use case Your team can maintain Performs well Scales with your needs Don\u0026rsquo;t choose based on trends—choose based on requirements! 🎯\n","permalink":"https://pixcave.com/posts/graphql-vs-rest-api/","summary":"\u003cp\u003eGraphQL and REST are both popular API design approaches. Here\u0026rsquo;s when to use each.\u003c/p\u003e\n\u003ch2 id=\"rest-api-overview\"\u003eREST API Overview\u003c/h2\u003e\n\u003cp\u003eREST (Representational State Transfer) uses HTTP methods to interact with resources.\u003c/p\u003e\n\u003ch3 id=\"characteristics\"\u003eCharacteristics\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eResource-based\u003c/strong\u003e: URLs represent resources\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHTTP methods\u003c/strong\u003e: GET, POST, PUT, DELETE\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStateless\u003c/strong\u003e: Each request is independent\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMultiple endpoints\u003c/strong\u003e: Different URLs for different resources\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"example\"\u003eExample\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET    /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET    /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePOST   /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePUT    /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eDELETE /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"graphql-overview\"\u003eGraphQL Overview\u003c/h2\u003e\n\u003cp\u003eGraphQL is a query language and runtime for APIs.\u003c/p\u003e","title":"GraphQL vs REST API: When to Use Which"},{"content":"Good API design is crucial for developer experience and system success. Here are best practices for designing RESTful APIs.\n1. Use RESTful Conventions Resource-Based URLs # Good: Resource-based GET /api/users GET /api/users/123 POST /api/users PUT /api/users/123 DELETE /api/users/123 # Bad: Action-based GET /api/getUsers POST /api/createUser POST /api/deleteUser HTTP Methods GET: Retrieve resources POST: Create resources PUT: Update entire resource PATCH: Partial update DELETE: Remove resource 2. Consistent Naming Use Plural Nouns # Good GET /api/users GET /api/orders GET /api/products # Bad GET /api/user GET /api/order GET /api/product Use kebab-case or camelCase # Good: Consistent GET /api/user-profiles GET /api/orderItems # Bad: Mixed GET /api/user_profiles GET /api/order-items 3. Version Your API URL Versioning GET /api/v1/users GET /api/v2/users Header Versioning GET /api/users Accept: application/vnd.api+json;version=2 4. Use Proper HTTP Status Codes Success Codes 200 OK # Successful GET, PUT, PATCH 201 Created # Successful POST 204 No Content # Successful DELETE Client Error Codes 400 Bad Request # Invalid request 401 Unauthorized # Authentication required 403 Forbidden # Not authorized 404 Not Found # Resource doesn\u0026#39;t exist 409 Conflict # Resource conflict 422 Unprocessable # Validation errors Server Error Codes 500 Internal Server Error 502 Bad Gateway 503 Service Unavailable 5. Consistent Response Format Standard Response Structure { \u0026#34;data\u0026#34;: { \u0026#34;id\u0026#34;: \u0026#34;123\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;user\u0026#34;, \u0026#34;attributes\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;John Doe\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;john@example.com\u0026#34; } }, \u0026#34;meta\u0026#34;: { \u0026#34;timestamp\u0026#34;: \u0026#34;2025-12-10T10:00:00Z\u0026#34; } } Error Response Format { \u0026#34;error\u0026#34;: { \u0026#34;code\u0026#34;: \u0026#34;VALIDATION_ERROR\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid input\u0026#34;, \u0026#34;details\u0026#34;: [ { \u0026#34;field\u0026#34;: \u0026#34;email\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid email format\u0026#34; } ] } } 6. Pagination Cursor-Based Pagination GET /api/users?cursor=eyJpZCI6IjEyMyJ9\u0026amp;limit=20 Response: { \u0026#34;data\u0026#34;: [...], \u0026#34;pagination\u0026#34;: { \u0026#34;cursor\u0026#34;: \u0026#34;eyJpZCI6IjE0MyJ9\u0026#34;, \u0026#34;has_more\u0026#34;: true } } Offset-Based Pagination GET /api/users?page=1\u0026amp;limit=20 Response: { \u0026#34;data\u0026#34;: [...], \u0026#34;pagination\u0026#34;: { \u0026#34;page\u0026#34;: 1, \u0026#34;limit\u0026#34;: 20, \u0026#34;total\u0026#34;: 100, \u0026#34;total_pages\u0026#34;: 5 } } 7. Filtering and Sorting Filtering GET /api/users?status=active\u0026amp;role=admin GET /api/orders?created_after=2024-01-01\u0026amp;created_before=2024-12-31 Sorting GET /api/users?sort=name,email\u0026amp;order=asc,desc GET /api/users?sort=-created_at # Descending 8. Field Selection Sparse Fieldsets GET /api/users?fields=id,name,email GET /api/users/123?fields=id,name Include Related Resources GET /api/users/123?include=orders,profile 9. Rate Limiting Headers X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1609459200 Response HTTP/1.1 429 Too Many Requests Retry-After: 60 10. Authentication and Authorization Use Standard Methods # Bearer token Authorization: Bearer \u0026lt;token\u0026gt; # API key X-API-Key: \u0026lt;key\u0026gt; Return Clear Errors { \u0026#34;error\u0026#34;: { \u0026#34;code\u0026#34;: \u0026#34;UNAUTHORIZED\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid or expired token\u0026#34; } } 11. Documentation OpenAPI/Swagger openapi: 3.0.0 info: title: User API version: 1.0.0 paths: /users: get: summary: List users responses: \u0026#39;200\u0026#39;: description: Success Interactive Documentation Swagger UI: Visual API documentation Postman: API testing and docs Redoc: Beautiful API docs 12. Error Handling Consistent Error Format { \u0026#34;error\u0026#34;: { \u0026#34;code\u0026#34;: \u0026#34;RESOURCE_NOT_FOUND\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;User with ID 123 not found\u0026#34;, \u0026#34;request_id\u0026#34;: \u0026#34;req_abc123\u0026#34; } } Validation Errors { \u0026#34;error\u0026#34;: { \u0026#34;code\u0026#34;: \u0026#34;VALIDATION_ERROR\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Validation failed\u0026#34;, \u0026#34;errors\u0026#34;: [ { \u0026#34;field\u0026#34;: \u0026#34;email\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid email format\u0026#34;, \u0026#34;code\u0026#34;: \u0026#34;INVALID_FORMAT\u0026#34; } ] } } 13. Caching Cache Headers Cache-Control: public, max-age=3600 ETag: \u0026#34;33a64df551425fcc55e4d42a148795d9f25f89d4\u0026#34; Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT Conditional Requests GET /api/users/123 If-None-Match: \u0026#34;33a64df551425fcc55e4d42a148795d9f25f89d4\u0026#34; # 304 Not Modified if unchanged 14. Security Best Practices Use HTTPS Always use HTTPS in production.\nInput Validation // Validate all inputs const schema = z.object({ email: z.string().email(), age: z.number().min(0).max(120), }); const result = schema.safeParse(req.body); Sanitize Output // Sanitize user input const sanitized = sanitizeHtml(userInput, { allowedTags: [], allowedAttributes: {}, }); 15. Performance Optimization Compression Content-Encoding: gzip Database Optimization Use indexes Avoid N+1 queries Use pagination Cache frequently accessed data Response Time Target: \u0026lt; 200ms for simple queries Acceptable: \u0026lt; 1s for complex queries Timeout: Set reasonable timeouts Tools API Development Postman: API testing Insomnia: API client HTTPie: Command-line client Documentation Swagger/OpenAPI: API specification Redoc: Documentation generator Stoplight: API design platform Testing Jest: Unit testing Supertest: API testing Newman: Postman CLI Conclusion Good API design:\nFollows conventions: RESTful principles Is consistent: Predictable patterns Is documented: Clear documentation Is secure: Authentication and validation Is performant: Fast and efficient Remember: Your API is a product. Design it with your users (developers) in mind.\nKey principles:\nConsistency: Same patterns throughout Simplicity: Easy to understand and use Documentation: Clear and comprehensive Versioning: Plan for changes Performance: Fast and efficient Happy API designing! 🚀\n","permalink":"https://pixcave.com/posts/api-design-best-practices/","summary":"\u003cp\u003eGood API design is crucial for developer experience and system success. Here are best practices for designing RESTful APIs.\u003c/p\u003e\n\u003ch2 id=\"1-use-restful-conventions\"\u003e1. Use RESTful Conventions\u003c/h2\u003e\n\u003ch3 id=\"resource-based-urls\"\u003eResource-Based URLs\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Good: Resource-based\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET    /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET    /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePOST   /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePUT    /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eDELETE /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Bad: Action-based\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET    /api/getUsers\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePOST   /api/createUser\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003ePOST   /api/deleteUser\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"http-methods\"\u003eHTTP Methods\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eGET\u003c/strong\u003e: Retrieve resources\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePOST\u003c/strong\u003e: Create resources\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePUT\u003c/strong\u003e: Update entire resource\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePATCH\u003c/strong\u003e: Partial update\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDELETE\u003c/strong\u003e: Remove resource\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-consistent-naming\"\u003e2. Consistent Naming\u003c/h2\u003e\n\u003ch3 id=\"use-plural-nouns\"\u003eUse Plural Nouns\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Good\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/orders\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/products\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Bad\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/order\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/product\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-kebab-case-or-camelcase\"\u003eUse kebab-case or camelCase\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Good: Consistent\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/user-profiles\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/orderItems\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Bad: Mixed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/user_profiles\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/order-items\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-version-your-api\"\u003e3. Version Your API\u003c/h2\u003e\n\u003ch3 id=\"url-versioning\"\u003eURL Versioning\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/v1/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/v2/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"header-versioning\"\u003eHeader Versioning\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eAccept: application/vnd.api+json;version=2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-use-proper-http-status-codes\"\u003e4. Use Proper HTTP Status Codes\u003c/h2\u003e\n\u003ch3 id=\"success-codes\"\u003eSuccess Codes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e200 OK          # Successful GET, PUT, PATCH\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e201 Created     # Successful POST\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e204 No Content  # Successful DELETE\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"client-error-codes\"\u003eClient Error Codes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e400 Bad Request      # Invalid request\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e401 Unauthorized     # Authentication required\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e403 Forbidden        # Not authorized\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e404 Not Found        # Resource doesn\u0026#39;t exist\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e409 Conflict         # Resource conflict\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e422 Unprocessable    # Validation errors\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"server-error-codes\"\u003eServer Error Codes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e500 Internal Server Error\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e502 Bad Gateway\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e503 Service Unavailable\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-consistent-response-format\"\u003e5. Consistent Response Format\u003c/h2\u003e\n\u003ch3 id=\"standard-response-structure\"\u003eStandard Response Structure\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;data\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;123\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;attributes\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;John Doe\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;john@example.com\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;meta\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;2025-12-10T10:00:00Z\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"error-response-format\"\u003eError Response Format\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;VALIDATION_ERROR\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid input\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;details\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;field\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid email format\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-pagination\"\u003e6. Pagination\u003c/h2\u003e\n\u003ch3 id=\"cursor-based-pagination\"\u003eCursor-Based Pagination\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?cursor=eyJpZCI6IjEyMyJ9\u0026amp;limit=20\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eResponse:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  \u0026#34;data\u0026#34;: [...],\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  \u0026#34;pagination\u0026#34;: {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;cursor\u0026#34;: \u0026#34;eyJpZCI6IjE0MyJ9\u0026#34;,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;has_more\u0026#34;: true\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"offset-based-pagination\"\u003eOffset-Based Pagination\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?page=1\u0026amp;limit=20\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eResponse:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  \u0026#34;data\u0026#34;: [...],\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  \u0026#34;pagination\u0026#34;: {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;page\u0026#34;: 1,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;limit\u0026#34;: 20,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;total\u0026#34;: 100,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e    \u0026#34;total_pages\u0026#34;: 5\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-filtering-and-sorting\"\u003e7. Filtering and Sorting\u003c/h2\u003e\n\u003ch3 id=\"filtering\"\u003eFiltering\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?status=active\u0026amp;role=admin\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/orders?created_after=2024-01-01\u0026amp;created_before=2024-12-31\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"sorting\"\u003eSorting\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?sort=name,email\u0026amp;order=asc,desc\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?sort=-created_at  # Descending\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"8-field-selection\"\u003e8. Field Selection\u003c/h2\u003e\n\u003ch3 id=\"sparse-fieldsets\"\u003eSparse Fieldsets\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users?fields=id,name,email\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users/123?fields=id,name\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"include-related-resources\"\u003eInclude Related Resources\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users/123?include=orders,profile\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"9-rate-limiting\"\u003e9. Rate Limiting\u003c/h2\u003e\n\u003ch3 id=\"headers\"\u003eHeaders\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eX-RateLimit-Limit: 1000\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eX-RateLimit-Remaining: 999\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eX-RateLimit-Reset: 1609459200\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"response\"\u003eResponse\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eHTTP\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1.1\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e429\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eToo Many Requests\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRetry-After\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"10-authentication-and-authorization\"\u003e10. Authentication and Authorization\u003c/h2\u003e\n\u003ch3 id=\"use-standard-methods\"\u003eUse Standard Methods\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# Bearer token\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eAuthorization: Bearer \u0026lt;token\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# API key\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eX-API-Key: \u0026lt;key\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"return-clear-errors\"\u003eReturn Clear Errors\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UNAUTHORIZED\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid or expired token\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"11-documentation\"\u003e11. Documentation\u003c/h2\u003e\n\u003ch3 id=\"openapiswagger\"\u003eOpenAPI/Swagger\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eopenapi\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e3.0.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003einfo\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003etitle\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eUser API\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eversion\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e1.0.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003epaths\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e/users\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eget\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003esummary\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eList users\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eresponses\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#39;200\u0026#39;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003edescription\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eSuccess\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"interactive-documentation\"\u003eInteractive Documentation\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSwagger UI\u003c/strong\u003e: Visual API documentation\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePostman\u003c/strong\u003e: API testing and docs\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRedoc\u003c/strong\u003e: Beautiful API docs\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"12-error-handling\"\u003e12. Error Handling\u003c/h2\u003e\n\u003ch3 id=\"consistent-error-format\"\u003eConsistent Error Format\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;RESOURCE_NOT_FOUND\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;User with ID 123 not found\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;request_id\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;req_abc123\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"validation-errors\"\u003eValidation Errors\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;VALIDATION_ERROR\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Validation failed\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;errors\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;field\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid email format\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;INVALID_FORMAT\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"13-caching\"\u003e13. Caching\u003c/h2\u003e\n\u003ch3 id=\"cache-headers\"\u003eCache Headers\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eCache-Control: public, max-age=3600\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eETag: \u0026#34;33a64df551425fcc55e4d42a148795d9f25f89d4\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eLast-Modified: Wed, 21 Oct 2015 07:28:00 GMT\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"conditional-requests\"\u003eConditional Requests\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eGET /api/users/123\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003eIf-None-Match: \u0026#34;33a64df551425fcc55e4d42a148795d9f25f89d4\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e# 304 Not Modified if unchanged\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"14-security-best-practices\"\u003e14. Security Best Practices\u003c/h2\u003e\n\u003ch3 id=\"use-https\"\u003eUse HTTPS\u003c/h3\u003e\n\u003cp\u003eAlways use HTTPS in production.\u003c/p\u003e","title":"API Design Best Practices: Building Developer-Friendly APIs"},{"content":"This write-up condenses the published DEV tutorial “Browser-based performance testing with K6” into an actionable walkthrough for frontend teams.\nWhy k6 browser Simulates real browser interactions (Chromium) vs. protocol-only tests. Captures Web Vitals (LCP/INP/CLS) and UX signals (spinners, interactivity). Reuses familiar k6 scripting with async/await + locators. Setup Install k6 (latest) and ensure Node/npm are available. Project skeleton: k6-tests/ libs/ # flows (login, add to cart, checkout) pages/ # Page Object Model classes tests/ # test entry scripts utils/ # shared options (browser config, VUs, iterations) Configure browser scenario (utils/k6-options.js): export const browserOptions = { scenarios: { ui: { executor: \u0026#34;shared-iterations\u0026#34;, vus: 1, iterations: 15, options: { browser: { type: \u0026#34;chromium\u0026#34; } }, }, }, }; Example flow (simplified) import { browser } from \u0026#34;k6/browser\u0026#34;; import { check } from \u0026#34;k6\u0026#34;; export const options = browserOptions; export default async function () { const page = await browser.newPage(); await page.goto(\u0026#34;https://www.saucedemo.com/\u0026#34;); await page.locator(\u0026#34;#user-name\u0026#34;).type(\u0026#34;standard_user\u0026#34;); await page.locator(\u0026#34;#password\u0026#34;).type(\u0026#34;secret_sauce\u0026#34;); await page.locator(\u0026#34;#login-button\u0026#34;).click(); check(page, { \u0026#34;login ok\u0026#34;: () =\u0026gt; page.locator(\u0026#34;.title\u0026#34;).textContent() === \u0026#34;Products\u0026#34; }); await page.close(); } Running \u0026amp; reporting CLI run: k6 run ./tests/buyItemsUserA.js Live dashboard: K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_OPEN=true k6 run ... Export HTML report: K6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=results/report.html Metrics to watch (aligns to Core Web Vitals) browser_web_vital_lcp — largest content paint; target \u0026lt; 2.5s p75. browser_web_vital_inp — interaction to next paint; target \u0026lt; 200ms p75. browser_web_vital_cls — layout shift; target \u0026lt; 0.1. Add custom checks for “spinner disappears”, “cart count”, “success message”. Tips Keep tests short and focused; one scenario per file. Reuse Page Objects for maintainability. Run with realistic VUs/iterations that mirror expected traffic. Use screenshots on failure for debuggability (page.screenshot()). Takeaway: k6 browser mode gives frontend teams reproducible, scriptable UX performance checks—ideal for catching regressions before they reach real users.\n","permalink":"https://pixcave.com/posts/browser-based-performance-testing-k6/","summary":"\u003cp\u003eThis write-up condenses the published DEV tutorial “Browser-based performance testing with K6” into an actionable walkthrough for frontend teams.\u003c/p\u003e\n\u003ch2 id=\"why-k6-browser\"\u003eWhy k6 browser\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSimulates real browser interactions (Chromium) vs. protocol-only tests.\u003c/li\u003e\n\u003cli\u003eCaptures Web Vitals (LCP/INP/CLS) and UX signals (spinners, interactivity).\u003c/li\u003e\n\u003cli\u003eReuses familiar k6 scripting with async/await + locators.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eInstall k6 (latest) and ensure Node/npm are available.\u003c/li\u003e\n\u003cli\u003eProject skeleton:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ek6-tests/\n  libs/      # flows (login, add to cart, checkout)\n  pages/     # Page Object Model classes\n  tests/     # test entry scripts\n  utils/     # shared options (browser config, VUs, iterations)\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"3\"\u003e\n\u003cli\u003eConfigure browser scenario (\u003ccode\u003eutils/k6-options.js\u003c/code\u003e):\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebrowserOptions\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003escenarios\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eui\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003eexecutor\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;shared-iterations\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003evus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003eiterations\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003eoptions\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ebrowser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;chromium\u0026#34;\u003c/span\u003e } },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"example-flow-simplified\"\u003eExample flow (simplified)\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ebrowser\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;k6/browser\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003echeck\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;k6\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoptions\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebrowserOptions\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebrowser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003enewPage\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003egoto\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://www.saucedemo.com/\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elocator\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#user-name\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;standard_user\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elocator\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#password\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;secret_sauce\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elocator\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#login-button\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eclick\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echeck\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e, { \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;login ok\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elocator\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.title\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etextContent\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Products\u0026#34;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epage\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclose\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"running--reporting\"\u003eRunning \u0026amp; reporting\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCLI run: \u003ccode\u003ek6 run ./tests/buyItemsUserA.js\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eLive dashboard: \u003ccode\u003eK6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_OPEN=true k6 run ...\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eExport HTML report: \u003ccode\u003eK6_WEB_DASHBOARD=true K6_WEB_DASHBOARD_EXPORT=results/report.html\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"metrics-to-watch-aligns-to-core-web-vitals\"\u003eMetrics to watch (aligns to Core Web Vitals)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003ebrowser_web_vital_lcp\u003c/code\u003e — largest content paint; target \u0026lt; 2.5s p75.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebrowser_web_vital_inp\u003c/code\u003e — interaction to next paint; target \u0026lt; 200ms p75.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebrowser_web_vital_cls\u003c/code\u003e — layout shift; target \u0026lt; 0.1.\u003c/li\u003e\n\u003cli\u003eAdd custom checks for “spinner disappears”, “cart count”, “success message”.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"tips\"\u003eTips\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep tests short and focused; one scenario per file.\u003c/li\u003e\n\u003cli\u003eReuse Page Objects for maintainability.\u003c/li\u003e\n\u003cli\u003eRun with realistic VUs/iterations that mirror expected traffic.\u003c/li\u003e\n\u003cli\u003eUse screenshots on failure for debuggability (\u003ccode\u003epage.screenshot()\u003c/code\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTakeaway:\u003c/strong\u003e k6 browser mode gives frontend teams reproducible, scriptable UX performance checks—ideal for catching regressions before they reach real users.\u003c/p\u003e","title":"Browser-based Performance Testing with k6: Hands-on Guide"},{"content":"This post distills the key ideas from the published DEV article “Frontend Performance Optimization: A Comprehensive Guide 🚀” into a concise, production-focused playbook.\nWhat matters Fast first paint and interaction: prioritize above-the-fold content, cut JS weight, avoid layout shifts. Ship less: smaller bundles, fewer blocking requests, cache aggressively. Ship smarter: load what’s needed when it’s needed (on demand and in priority order). Core techniques 1) Selective rendering Render only what is visible (e.g., IntersectionObserver + skeletons). Defer heavy components until scrolled into view. 2) Code splitting \u0026amp; dynamic imports Split by route/feature; lazy-load non-critical views. Example (React): const Page = lazy(() =\u0026gt; import(\u0026#34;./Page\u0026#34;)); \u0026lt;Suspense fallback={\u0026lt;div\u0026gt;Loading…\u0026lt;/div\u0026gt;}\u0026gt; \u0026lt;Page /\u0026gt; \u0026lt;/Suspense\u0026gt;; 3) Prefetching \u0026amp; caching Prefetch likely-next routes/assets (\u0026lt;link rel=\u0026quot;prefetch\u0026quot;\u0026gt; or router prefetch). Pre-warm API data with React Query/Next.js loader functions. 4) Priority-based loading Preload critical CSS/hero imagery: \u0026lt;link rel=\u0026quot;preload\u0026quot; as=\u0026quot;style\u0026quot; href=\u0026quot;styles.css\u0026quot;\u0026gt;. Use defer/async for non-critical scripts. 5) Compression \u0026amp; transfer Enable Brotli/Gzip at the edge; pre-compress static assets in CI/CD. Serve modern formats (AVIF/WebP) and keep caching headers long-lived. 6) Loading sequence hygiene Order: HTML → critical CSS → critical JS → images/fonts → analytics. Avoid long main-thread tasks; prefer requestIdleCallback for non-urgent work. 7) Tree shaking \u0026amp; dead-code elimination Use ESM named imports; avoid import *. Keep build in production mode with minification + module side-effects flags. Measurement \u0026amp; guardrails Track Core Web Vitals (LCP, INP, CLS) plus TTFB and bundle size per release. Run Lighthouse/WebPageTest in CI; fail builds on regressions above agreed budgets. Monitor real-user metrics (RUM) to validate improvements after deploys. Quick starter checklist Lazy-load routes and heavy widgets. Preload hero font/hero image; inline critical CSS if needed. Turn on Brotli at CDN; cache static assets with versioned filenames. Set performance budgets (JS \u0026lt; 200KB gz, LCP \u0026lt; 2.5s p75, INP \u0026lt; 200ms). Automate audits in CI and watch RUM dashboards after each release. Bottom line: Combine “ship less” (smaller, shaken, compressed bundles) with “ship smarter” (prioritized, on-demand loading) and enforce budgets with automated checks to keep your app fast over time.\n","permalink":"https://pixcave.com/posts/frontend-performance-optimization-guide/","summary":"\u003cp\u003eThis post distills the key ideas from the published DEV article “Frontend Performance Optimization: A Comprehensive Guide 🚀” into a concise, production-focused playbook.\u003c/p\u003e\n\u003ch2 id=\"what-matters\"\u003eWhat matters\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFast first paint and interaction: prioritize above-the-fold content, cut JS weight, avoid layout shifts.\u003c/li\u003e\n\u003cli\u003eShip less: smaller bundles, fewer blocking requests, cache aggressively.\u003c/li\u003e\n\u003cli\u003eShip smarter: load what’s needed when it’s needed (on demand and in priority order).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"core-techniques\"\u003eCore techniques\u003c/h2\u003e\n\u003ch3 id=\"1-selective-rendering\"\u003e1) Selective rendering\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eRender only what is visible (e.g., \u003ccode\u003eIntersectionObserver\u003c/code\u003e + skeletons).\u003c/li\u003e\n\u003cli\u003eDefer heavy components until scrolled into view.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"2-code-splitting--dynamic-imports\"\u003e2) Code splitting \u0026amp; dynamic imports\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSplit by route/feature; lazy-load non-critical views.\u003c/li\u003e\n\u003cli\u003eExample (React):\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePage\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elazy\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;./Page\u0026#34;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eSuspense\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efallback\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eLoading\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e…\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;}\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ePage\u003c/span\u003e /\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eSuspense\u003c/span\u003e\u0026gt;;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-prefetching--caching\"\u003e3) Prefetching \u0026amp; caching\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ePrefetch likely-next routes/assets (\u003ccode\u003e\u0026lt;link rel=\u0026quot;prefetch\u0026quot;\u0026gt;\u003c/code\u003e or router prefetch).\u003c/li\u003e\n\u003cli\u003ePre-warm API data with React Query/Next.js loader functions.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"4-priority-based-loading\"\u003e4) Priority-based loading\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ePreload critical CSS/hero imagery: \u003ccode\u003e\u0026lt;link rel=\u0026quot;preload\u0026quot; as=\u0026quot;style\u0026quot; href=\u0026quot;styles.css\u0026quot;\u0026gt;\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003edefer\u003c/code\u003e/\u003ccode\u003easync\u003c/code\u003e for non-critical scripts.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"5-compression--transfer\"\u003e5) Compression \u0026amp; transfer\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eEnable Brotli/Gzip at the edge; pre-compress static assets in CI/CD.\u003c/li\u003e\n\u003cli\u003eServe modern formats (AVIF/WebP) and keep caching headers long-lived.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"6-loading-sequence-hygiene\"\u003e6) Loading sequence hygiene\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eOrder: HTML → critical CSS → critical JS → images/fonts → analytics.\u003c/li\u003e\n\u003cli\u003eAvoid long main-thread tasks; prefer \u003ccode\u003erequestIdleCallback\u003c/code\u003e for non-urgent work.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"7-tree-shaking--dead-code-elimination\"\u003e7) Tree shaking \u0026amp; dead-code elimination\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eUse ESM named imports; avoid \u003ccode\u003eimport *\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eKeep build in production mode with minification + module side-effects flags.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"measurement--guardrails\"\u003eMeasurement \u0026amp; guardrails\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eTrack Core Web Vitals (LCP, INP, CLS) plus TTFB and bundle size per release.\u003c/li\u003e\n\u003cli\u003eRun Lighthouse/WebPageTest in CI; fail builds on regressions above agreed budgets.\u003c/li\u003e\n\u003cli\u003eMonitor real-user metrics (RUM) to validate improvements after deploys.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"quick-starter-checklist\"\u003eQuick starter checklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Lazy-load routes and heavy widgets.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Preload hero font/hero image; inline critical CSS if needed.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Turn on Brotli at CDN; cache static assets with versioned filenames.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Set performance budgets (JS \u0026lt; 200KB gz, LCP \u0026lt; 2.5s p75, INP \u0026lt; 200ms).\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Automate audits in CI and watch RUM dashboards after each release.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eBottom line:\u003c/strong\u003e Combine “ship less” (smaller, shaken, compressed bundles) with “ship smarter” (prioritized, on-demand loading) and enforce budgets with automated checks to keep your app fast over time.\u003c/p\u003e","title":"Frontend Performance Optimization: A Condensed Playbook"},{"content":"This article summarizes the DEV post “How to Use React Query for Efficient Data Fetching” and focuses on a minimal, production-ready setup.\nWhy React Query (TanStack Query) Handles fetching, caching, retries, background refresh, and deduping. Removes useEffect + manual loading/error state boilerplate. Scales to pagination, infinite scroll, and SSR hydration. 3-step setup Install: npm install @tanstack/react-query Create a client and wrap your app: import { QueryClient, QueryClientProvider } from \u0026#34;@tanstack/react-query\u0026#34;; const queryClient = new QueryClient(); const App = () =\u0026gt; ( \u0026lt;QueryClientProvider client={queryClient}\u0026gt; \u0026lt;MyComponent /\u0026gt; \u0026lt;/QueryClientProvider\u0026gt; ); Fetch with useQuery: import { useQuery } from \u0026#34;@tanstack/react-query\u0026#34;; function UsersList() { const { data, isLoading, error } = useQuery({ queryKey: [\u0026#34;users\u0026#34;], queryFn: () =\u0026gt; fetch(\u0026#34;/api/users\u0026#34;).then((r) =\u0026gt; r.json()), }); if (isLoading) return \u0026lt;p\u0026gt;Loading…\u0026lt;/p\u0026gt;; if (error) return \u0026lt;p\u0026gt;Something went wrong\u0026lt;/p\u0026gt;; return \u0026lt;ul\u0026gt;{data.map((u) =\u0026gt; \u0026lt;li key={u.id}\u0026gt;{u.name}\u0026lt;/li\u0026gt;)}\u0026lt;/ul\u0026gt;; } Features you get “for free” Auto refetch on window focus/network reconnect. Stale-while-revalidate caching with configurable TTLs. Retries with exponential backoff for transient failures. Query invalidation to refresh related data after mutations. Devtools for live inspection of query states. Power tips Prefetch likely-next routes to hide latency (e.g., on hover). Use useInfiniteQuery for endless scroll; surface hasNextPage/fetchNextPage. Pass auth tokens via queryFnContext; centralize fetcher. For SSR/Next.js, hydrate with dehydrate/Hydrate to avoid waterfalls. Performance guardrails Set per-query stale times and retry counts to balance freshness vs. load. Log slow queries and cache hit rate; watch INP/LCP when triggering refetches. Keep query keys stable and descriptive (e.g., [\u0026quot;post\u0026quot;, postId]). Bottom line: React Query removes state-management overhead for remote data and delivers faster, more resilient UIs with minimal code.\n","permalink":"https://pixcave.com/posts/react-query-efficient-data-fetching/","summary":"\u003cp\u003eThis article summarizes the DEV post “How to Use React Query for Efficient Data Fetching” and focuses on a minimal, production-ready setup.\u003c/p\u003e\n\u003ch2 id=\"why-react-query-tanstack-query\"\u003eWhy React Query (TanStack Query)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHandles fetching, caching, retries, background refresh, and deduping.\u003c/li\u003e\n\u003cli\u003eRemoves \u003ccode\u003euseEffect\u003c/code\u003e + manual loading/error state boilerplate.\u003c/li\u003e\n\u003cli\u003eScales to pagination, infinite scroll, and SSR hydration.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"3-step-setup\"\u003e3-step setup\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eInstall: \u003ccode\u003enpm install @tanstack/react-query\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eCreate a client and wrap your app:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eQueryClient\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eQueryClientProvider\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@tanstack/react-query\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003equeryClient\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eQueryClient\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () =\u0026gt; (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003eQueryClientProvider\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003equeryClient\u003c/span\u003e}\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eMyComponent\u003c/span\u003e /\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eQueryClientProvider\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"3\"\u003e\n\u003cli\u003eFetch with \u003ccode\u003euseQuery\u003c/code\u003e:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003euseQuery\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@tanstack/react-query\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUsersList\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eisLoading\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e } \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseQuery\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003equeryKey\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003equeryFn\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003efetch\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/api/users\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ethen\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003er\u003c/span\u003e) =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003er\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ejson\u003c/span\u003e()),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eisLoading\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eLoading\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e…\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eSomething\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewent\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewrong\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003eul\u003c/span\u003e\u0026gt;{\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e) =\u0026gt; \u0026lt;\u003cspan style=\"color:#f92672\"\u003eli\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e}\u0026gt;{\u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eli\u003c/span\u003e\u0026gt;)}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eul\u003c/span\u003e\u0026gt;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"features-you-get-for-free\"\u003eFeatures you get “for free”\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAuto refetch on window focus/network reconnect.\u003c/li\u003e\n\u003cli\u003eStale-while-revalidate caching with configurable TTLs.\u003c/li\u003e\n\u003cli\u003eRetries with exponential backoff for transient failures.\u003c/li\u003e\n\u003cli\u003eQuery invalidation to refresh related data after mutations.\u003c/li\u003e\n\u003cli\u003eDevtools for live inspection of query states.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"power-tips\"\u003ePower tips\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrefetch likely-next routes to hide latency (e.g., on hover).\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003euseInfiniteQuery\u003c/code\u003e for endless scroll; surface \u003ccode\u003ehasNextPage\u003c/code\u003e/\u003ccode\u003efetchNextPage\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003ePass auth tokens via \u003ccode\u003equeryFnContext\u003c/code\u003e; centralize fetcher.\u003c/li\u003e\n\u003cli\u003eFor SSR/Next.js, hydrate with \u003ccode\u003edehydrate\u003c/code\u003e/\u003ccode\u003eHydrate\u003c/code\u003e to avoid waterfalls.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"performance-guardrails\"\u003ePerformance guardrails\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet per-query stale times and retry counts to balance freshness vs. load.\u003c/li\u003e\n\u003cli\u003eLog slow queries and cache hit rate; watch INP/LCP when triggering refetches.\u003c/li\u003e\n\u003cli\u003eKeep query keys stable and descriptive (e.g., \u003ccode\u003e[\u0026quot;post\u0026quot;, postId]\u003c/code\u003e).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eBottom line:\u003c/strong\u003e React Query removes state-management overhead for remote data and delivers faster, more resilient UIs with minimal code.\u003c/p\u003e","title":"React Query for Efficient Data Fetching (2025 Quickstart)"},{"content":"Coming from JavaScript to Rust? Here\u0026rsquo;s a practical guide to help you make the transition.\nWhy Rust? Rust offers:\nMemory safety without garbage collection Performance comparable to C/C++ Modern tooling and package management WebAssembly support for web development Growing ecosystem with active community Key Differences 1. Ownership System Rust\u0026rsquo;s ownership system is unique:\n// Rust: Ownership let s1 = String::from(\u0026#34;hello\u0026#34;); let s2 = s1; // s1 is moved to s2 // println!(\u0026#34;{}\u0026#34;, s1); // Error: s1 is no longer valid // JavaScript: Reference let s1 = \u0026#34;hello\u0026#34;; let s2 = s1; // s1 is still valid console.log(s1); // Works fine 2. Mutability Rust requires explicit mutability:\n// Rust let x = 5; // Immutable let mut y = 10; // Mutable y = 20; // OK // JavaScript let x = 5; // Mutable by default x = 10; // OK const y = 10; // Immutable 3. Type System Rust has a strong, static type system:\n// Rust: Explicit types let x: i32 = 42; let name: String = String::from(\u0026#34;John\u0026#34;); // JavaScript: Dynamic types let x = 42; let name = \u0026#34;John\u0026#34;; Common Patterns Variables and Mutability // Immutable variable let x = 5; // Mutable variable let mut y = 10; y = 20; // Constants const MAX_POINTS: u32 = 100_000; Functions // Rust function fn add(x: i32, y: i32) -\u0026gt; i32 { x + y // No semicolon = return value } // With explicit return fn subtract(x: i32, y: i32) -\u0026gt; i32 { return x - y; } // JavaScript equivalent function add(x, y) { return x + y; } Structs (Objects) // Rust struct struct User { name: String, age: u32, email: String, } impl User { fn new(name: String, age: u32, email: String) -\u0026gt; Self { User { name, age, email } } fn greet(\u0026amp;self) { println!(\u0026#34;Hello, I\u0026#39;m {}\u0026#34;, self.name); } } // Usage let user = User::new( String::from(\u0026#34;John\u0026#34;), 30, String::from(\u0026#34;john@example.com\u0026#34;), ); user.greet(); Enums and Pattern Matching // Rust enum enum Status { Pending, Approved, Rejected, } // Pattern matching fn handle_status(status: Status) { match status { Status::Pending =\u0026gt; println!(\u0026#34;Processing...\u0026#34;), Status::Approved =\u0026gt; println!(\u0026#34;Approved!\u0026#34;), Status::Rejected =\u0026gt; println!(\u0026#34;Rejected.\u0026#34;), } } // Enum with data enum Result\u0026lt;T, E\u0026gt; { Ok(T), Err(E), } Error Handling // Rust: Result type fn divide(a: f64, b: f64) -\u0026gt; Result\u0026lt;f64, String\u0026gt; { if b == 0.0 { Err(String::from(\u0026#34;Division by zero\u0026#34;)) } else { Ok(a / b) } } // Usage match divide(10.0, 2.0) { Ok(result) =\u0026gt; println!(\u0026#34;Result: {}\u0026#34;, result), Err(error) =\u0026gt; println!(\u0026#34;Error: {}\u0026#34;, error), } // With ? operator fn calculate() -\u0026gt; Result\u0026lt;f64, String\u0026gt; { let result = divide(10.0, 2.0)?; Ok(result * 2.0) } Collections // Vector (array) let mut vec = Vec::new(); vec.push(1); vec.push(2); vec.push(3); // Or with macro let vec = vec![1, 2, 3]; // HashMap use std::collections::HashMap; let mut map = HashMap::new(); map.insert(\u0026#34;key1\u0026#34;, \u0026#34;value1\u0026#34;); map.insert(\u0026#34;key2\u0026#34;, \u0026#34;value2\u0026#34;); Iterators // Rust iterators let numbers = vec![1, 2, 3, 4, 5]; let doubled: Vec\u0026lt;i32\u0026gt; = numbers .iter() .map(|x| x * 2) .filter(|x| x \u0026gt; \u0026amp;5) .collect(); // JavaScript equivalent const numbers = [1, 2, 3, 4, 5]; const doubled = numbers .map(x =\u0026gt; x * 2) .filter(x =\u0026gt; x \u0026gt; 5); Web Development with Rust WebAssembly Compile Rust to WebAssembly:\n// src/lib.rs use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn add(a: i32, b: i32) -\u0026gt; i32 { a + b } #[wasm_bindgen] pub struct Calculator { value: i32, } #[wasm_bindgen] impl Calculator { #[wasm_bindgen(constructor)] pub fn new() -\u0026gt; Calculator { Calculator { value: 0 } } #[wasm_bindgen] pub fn add(\u0026amp;mut self, n: i32) { self.value += n; } #[wasm_bindgen] pub fn get_value(\u0026amp;self) -\u0026gt; i32 { self.value } } Web Frameworks Popular Rust web frameworks:\nActix Web: High-performance, actor-based Rocket: Easy to use, type-safe Axum: Modern, async-first Warp: Lightweight, functional Learning Path 1. Start with Basics Variables and types Functions and control flow Ownership and borrowing Structs and enums 2. Practice with Projects Command-line tools Web servers WebAssembly modules System utilities 3. Learn Advanced Concepts Lifetimes Traits and generics Async/await Macros Common Pitfalls 1. Fighting the Borrow Checker // Common error let s = String::from(\u0026#34;hello\u0026#34;); let r1 = \u0026amp;s; let r2 = \u0026amp;s; // OK: multiple immutable references let r3 = \u0026amp;mut s; // Error: can\u0026#39;t have mutable and immutable references 2. Moving Values // Error: value moved let s1 = String::from(\u0026#34;hello\u0026#34;); let s2 = s1; println!(\u0026#34;{}\u0026#34;, s1); // Error: s1 was moved // Solution: Clone let s1 = String::from(\u0026#34;hello\u0026#34;); let s2 = s1.clone(); println!(\u0026#34;{}\u0026#34;, s1); // OK 3. Lifetime Annotations // Lifetime annotation needed fn longest\u0026lt;\u0026#39;a\u0026gt;(x: \u0026amp;\u0026#39;a str, y: \u0026amp;\u0026#39;a str) -\u0026gt; \u0026amp;\u0026#39;a str { if x.len() \u0026gt; y.len() { x } else { y } } Resources Official The Rust Book Rust by Example Rustlings Tools cargo - Package manager rustfmt - Code formatter clippy - Linter rust-analyzer - Language server Conclusion Rust offers:\nSafety: Memory safety without GC Performance: Near C/C++ speed Modern: Great tooling and ecosystem Versatile: Systems programming to web The learning curve is steep, but the benefits are worth it:\nFewer bugs Better performance Modern tooling Growing ecosystem Start small, practice regularly, and don\u0026rsquo;t fight the borrow checker—work with it!\nHappy Rusting! 🦀\n","permalink":"https://pixcave.com/posts/rust-for-javascript-developers/","summary":"\u003cp\u003eComing from JavaScript to Rust? Here\u0026rsquo;s a practical guide to help you make the transition.\u003c/p\u003e\n\u003ch2 id=\"why-rust\"\u003eWhy Rust?\u003c/h2\u003e\n\u003cp\u003eRust offers:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMemory safety\u003c/strong\u003e without garbage collection\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePerformance\u003c/strong\u003e comparable to C/C++\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eModern tooling\u003c/strong\u003e and package management\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWebAssembly\u003c/strong\u003e support for web development\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGrowing ecosystem\u003c/strong\u003e with active community\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"key-differences\"\u003eKey Differences\u003c/h2\u003e\n\u003ch3 id=\"1-ownership-system\"\u003e1. Ownership System\u003c/h3\u003e\n\u003cp\u003eRust\u0026rsquo;s ownership system is unique:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Rust: Ownership\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String::from(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s1; \u003cspan style=\"color:#75715e\"\u003e// s1 is moved to s2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// println!(\u0026#34;{}\u0026#34;, s1); // Error: s1 is no longer valid\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// JavaScript: Reference\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s1; \u003cspan style=\"color:#75715e\"\u003e// s1 is still valid\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003econsole.log(s1); \u003cspan style=\"color:#75715e\"\u003e// Works fine\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-mutability\"\u003e2. Mutability\u003c/h3\u003e\n\u003cp\u003eRust requires explicit mutability:\u003c/p\u003e","title":"Rust for JavaScript Developers: A Practical Guide"},{"content":"TypeScript has become the de facto standard for large-scale JavaScript applications. Here are the best practices to write better type-safe code in 2025.\n1. Use Strict Mode Always enable strict mode in tsconfig.json:\n{ \u0026#34;compilerOptions\u0026#34;: { \u0026#34;strict\u0026#34;: true, \u0026#34;noImplicitAny\u0026#34;: true, \u0026#34;strictNullChecks\u0026#34;: true, \u0026#34;strictFunctionTypes\u0026#34;: true, \u0026#34;strictBindCallApply\u0026#34;: true, \u0026#34;strictPropertyInitialization\u0026#34;: true, \u0026#34;noImplicitThis\u0026#34;: true, \u0026#34;alwaysStrict\u0026#34;: true } } 2. Prefer Interfaces for Object Shapes Use interfaces for object shapes, types for unions/intersections:\n// Good: Interface for object shape interface User { id: string; name: string; email: string; } // Good: Type for union type Status = \u0026#39;pending\u0026#39; | \u0026#39;approved\u0026#39; | \u0026#39;rejected\u0026#39;; // Good: Type for intersection type AdminUser = User \u0026amp; { role: \u0026#39;admin\u0026#39; }; 3. Use Discriminated Unions Make type narrowing easier with discriminated unions:\ntype Result\u0026lt;T\u0026gt; = | { success: true; data: T } | { success: false; error: string }; function handleResult\u0026lt;T\u0026gt;(result: Result\u0026lt;T\u0026gt;) { if (result.success) { // TypeScript knows result.data exists console.log(result.data); } else { // TypeScript knows result.error exists console.error(result.error); } } 4. Avoid any, Use unknown Never use any, use unknown for truly unknown types:\n// Bad function processData(data: any) { return data.value; } // Good function processData(data: unknown) { if (typeof data === \u0026#39;object\u0026#39; \u0026amp;\u0026amp; data !== null \u0026amp;\u0026amp; \u0026#39;value\u0026#39; in data) { return (data as { value: string }).value; } throw new Error(\u0026#39;Invalid data\u0026#39;); } // Better: Use type guards function isDataWithValue(data: unknown): data is { value: string } { return typeof data === \u0026#39;object\u0026#39; \u0026amp;\u0026amp; data !== null \u0026amp;\u0026amp; \u0026#39;value\u0026#39; in data; } function processData(data: unknown) { if (isDataWithValue(data)) { return data.value; // Type-safe! } throw new Error(\u0026#39;Invalid data\u0026#39;); } 5. Use const Assertions Preserve literal types with as const:\n// Without const assertion const colors = [\u0026#39;red\u0026#39;, \u0026#39;green\u0026#39;, \u0026#39;blue\u0026#39;]; // string[] // With const assertion const colors = [\u0026#39;red\u0026#39;, \u0026#39;green\u0026#39;, \u0026#39;blue\u0026#39;] as const; // readonly [\u0026#34;red\u0026#34;, \u0026#34;green\u0026#34;, \u0026#34;blue\u0026#34;] // Extract union type type Color = typeof colors[number]; // \u0026#34;red\u0026#34; | \u0026#34;green\u0026#34; | \u0026#34;blue\u0026#34; 6. Use Utility Types Leverage built-in utility types:\ninterface User { id: string; name: string; email: string; password: string; } // Partial: Make all properties optional type PartialUser = Partial\u0026lt;User\u0026gt;; // Pick: Select specific properties type PublicUser = Pick\u0026lt;User, \u0026#39;id\u0026#39; | \u0026#39;name\u0026#39; | \u0026#39;email\u0026#39;\u0026gt;; // Omit: Exclude specific properties type UserWithoutPassword = Omit\u0026lt;User, \u0026#39;password\u0026#39;\u0026gt;; // Required: Make all properties required type RequiredUser = Required\u0026lt;PartialUser\u0026gt;; // Readonly: Make all properties readonly type ReadonlyUser = Readonly\u0026lt;User\u0026gt;; 7. Use Generic Constraints Constrain generics for type safety:\n// Bad: Too permissive function getValue\u0026lt;T\u0026gt;(obj: T, key: string) { return obj[key]; // Error: can\u0026#39;t index T with string } // Good: Constrained generic function getValue\u0026lt;T extends Record\u0026lt;string, unknown\u0026gt;\u0026gt;( obj: T, key: keyof T ): T[keyof T] { return obj[key]; } // Usage const user = { name: \u0026#39;John\u0026#39;, age: 30 }; const name = getValue(user, \u0026#39;name\u0026#39;); // string const age = getValue(user, \u0026#39;age\u0026#39;); // number 8. Prefer Function Overloads for Complex Signatures Use function overloads for better type inference:\n// Function overloads function format(value: string): string; function format(value: number): string; function format(value: Date): string; function format(value: string | number | Date): string { if (value instanceof Date) { return value.toISOString(); } return String(value); } // Usage const str = format(\u0026#39;hello\u0026#39;); // string const num = format(42); // string const date = format(new Date()); // string 9. Use Template Literal Types Create powerful string types:\ntype HttpMethod = \u0026#39;GET\u0026#39; | \u0026#39;POST\u0026#39; | \u0026#39;PUT\u0026#39; | \u0026#39;DELETE\u0026#39;; type ApiEndpoint = `/api/${string}`; type FullEndpoint = `${HttpMethod} ${ApiEndpoint}`; // Usage const endpoint: FullEndpoint = \u0026#39;GET /api/users\u0026#39;; 10. Use satisfies Operator (TypeScript 4.9+) Ensure values match types without widening:\n// Without satisfies const config = { apiUrl: \u0026#39;https://api.example.com\u0026#39;, timeout: 5000, }; // Type is inferred, might be too wide // With satisfies const config = { apiUrl: \u0026#39;https://api.example.com\u0026#39;, timeout: 5000, } satisfies { apiUrl: string; timeout: number; }; // Type is checked but not widened 11. Avoid Type Assertions Prefer type guards over type assertions:\n// Bad: Type assertion function processUser(data: unknown) { const user = data as User; return user.name; // Unsafe! } // Good: Type guard function isUser(data: unknown): data is User { return ( typeof data === \u0026#39;object\u0026#39; \u0026amp;\u0026amp; data !== null \u0026amp;\u0026amp; \u0026#39;id\u0026#39; in data \u0026amp;\u0026amp; \u0026#39;name\u0026#39; in data \u0026amp;\u0026amp; \u0026#39;email\u0026#39; in data ); } function processUser(data: unknown) { if (isUser(data)) { return data.name; // Type-safe! } throw new Error(\u0026#39;Invalid user data\u0026#39;); } 12. Use branded Types for Nominal Typing Create distinct types for the same underlying type:\ntype UserId = string \u0026amp; { readonly brand: unique symbol }; type ProductId = string \u0026amp; { readonly brand: unique symbol }; function createUserId(id: string): UserId { return id as UserId; } function createProductId(id: string): ProductId { return id as ProductId; } // Usage const userId = createUserId(\u0026#39;123\u0026#39;); const productId = createProductId(\u0026#39;123\u0026#39;); // Type error: can\u0026#39;t mix UserId and ProductId function getUser(id: UserId) { /* ... */ } getUser(productId); // Error! 13. Use const for Immutable Data Prefer const for immutable references:\n// Bad: Mutable array let items = [1, 2, 3]; items.push(4); // Mutation allowed // Good: Readonly array const items = [1, 2, 3] as const; // items.push(4); // Error: readonly // Good: Readonly type const items: readonly number[] = [1, 2, 3]; 14. Use Index Signatures Carefully Be specific with index signatures:\n// Bad: Too permissive interface Config { [key: string]: any; } // Good: More specific interface Config { [key: string]: string | number | boolean; } // Better: Use Record utility type type Config = Record\u0026lt;string, string | number | boolean\u0026gt;; // Best: Be explicit when possible interface Config { apiUrl: string; timeout: number; retries: number; [key: string]: string | number; // Only for truly dynamic keys } 15. Use never for Exhaustiveness Checking Ensure all cases are handled:\ntype Status = \u0026#39;pending\u0026#39; | \u0026#39;approved\u0026#39; | \u0026#39;rejected\u0026#39;; function handleStatus(status: Status) { switch (status) { case \u0026#39;pending\u0026#39;: return \u0026#39;Processing...\u0026#39;; case \u0026#39;approved\u0026#39;: return \u0026#39;Approved!\u0026#39;; case \u0026#39;rejected\u0026#39;: return \u0026#39;Rejected.\u0026#39;; default: // TypeScript ensures all cases are handled const exhaustive: never = status; return exhaustive; } } 16. Use Mapped Types for Transformations Create new types from existing ones:\ntype Optional\u0026lt;T\u0026gt; = { [K in keyof T]?: T[K]; }; type Nullable\u0026lt;T\u0026gt; = { [K in keyof T]: T[K] | null; }; type Getters\u0026lt;T\u0026gt; = { [K in keyof T as `get${Capitalize\u0026lt;string \u0026amp; K\u0026gt;}`]: () =\u0026gt; T[K]; }; 17. Prefer Composition Over Inheritance Use composition with types:\n// Bad: Inheritance class User extends BaseEntity { // ... } // Good: Composition type User = BaseEntity \u0026amp; { name: string; email: string; }; 18. Use readonly for Immutability Mark properties as readonly when appropriate:\ninterface Config { readonly apiUrl: string; readonly timeout: number; } const config: Config = { apiUrl: \u0026#39;https://api.example.com\u0026#39;, timeout: 5000, }; // config.apiUrl = \u0026#39;...\u0026#39;; // Error: readonly 19. Use as const with Enums Prefer as const objects over enums:\n// Bad: Enum enum Status { Pending = \u0026#39;pending\u0026#39;, Approved = \u0026#39;approved\u0026#39;, Rejected = \u0026#39;rejected\u0026#39;, } // Good: const object const Status = { Pending: \u0026#39;pending\u0026#39;, Approved: \u0026#39;approved\u0026#39;, Rejected: \u0026#39;rejected\u0026#39;, } as const; type Status = typeof Status[keyof typeof Status]; 20. Document Complex Types Add JSDoc comments for complex types:\n/** * Represents a user in the system. * * @property id - Unique identifier * @property name - User\u0026#39;s full name * @property email - User\u0026#39;s email address * @property role - User\u0026#39;s role in the system */ interface User { id: string; name: string; email: string; role: \u0026#39;admin\u0026#39; | \u0026#39;user\u0026#39; | \u0026#39;guest\u0026#39;; } Tools and Resources Type Checking tsc --noEmit - Type check without emitting ESLint with TypeScript rules typescript-eslint - Enhanced linting Type Utilities type-fest - Useful type utilities ts-toolbelt - Type utilities library utility-types - TypeScript utility types Testing tsd - Type testing library @typescript-eslint/parser - ESLint parser Conclusion Following these best practices will help you:\nWrite safer code: Catch errors at compile time Improve maintainability: Clear, self-documenting types Enhance developer experience: Better IDE support Reduce bugs: Type safety prevents common errors Remember: TypeScript is a tool to help you write better JavaScript. Use it wisely, but don\u0026rsquo;t over-engineer. Sometimes, simpler is better.\nHappy typing! 🎯\n","permalink":"https://pixcave.com/posts/typescript-best-practices-2025/","summary":"\u003cp\u003eTypeScript has become the de facto standard for large-scale JavaScript applications. Here are the best practices to write better type-safe code in 2025.\u003c/p\u003e\n\u003ch2 id=\"1-use-strict-mode\"\u003e1. Use Strict Mode\u003c/h2\u003e\n\u003cp\u003eAlways enable strict mode in \u003ccode\u003etsconfig.json\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;compilerOptions\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;strict\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;noImplicitAny\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;strictNullChecks\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;strictFunctionTypes\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;strictBindCallApply\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;strictPropertyInitialization\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;noImplicitThis\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;alwaysStrict\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-prefer-interfaces-for-object-shapes\"\u003e2. Prefer Interfaces for Object Shapes\u003c/h2\u003e\n\u003cp\u003eUse interfaces for object shapes, types for unions/intersections:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Interface for object shape\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Type for union\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eStatus\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;pending\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;approved\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rejected\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Type for intersection\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAdminUser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003erole\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;admin\u0026#39;\u003c/span\u003e };\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-use-discriminated-unions\"\u003e3. Use Discriminated Unions\u003c/h2\u003e\n\u003cp\u003eMake type narrowing easier with discriminated unions:\u003c/p\u003e","title":"TypeScript Best Practices for 2025: Write Better Type-Safe Code"},{"content":"Here are 9 developer productivity tools that can dramatically improve your workflow and save you hours every week.\n1. Warp Terminal What it is: A modern, Rust-based terminal with AI assistance.\nWhy it\u0026rsquo;s great:\nAI command suggestions Split panes and tabs Command palette Better autocomplete Integrated workflows Use case: Replace your default terminal for a better development experience.\n2. Cursor AI Editor What it is: VS Code fork with built-in AI coding assistant.\nWhy it\u0026rsquo;s great:\nAI-powered code completion Natural language to code Context-aware suggestions Refactoring assistance Code explanation Use case: Write code faster with AI assistance that understands your codebase.\n3. Raycast What it is: Spotlight replacement for Mac with powerful extensions.\nWhy it\u0026rsquo;s great:\nQuick app launcher Clipboard history Window management Calculator and conversions Custom workflows Integration with dev tools Use case: Replace Spotlight and automate repetitive tasks.\n4. GitHub Copilot Workspace What it is: AI-powered development environment.\nWhy it\u0026rsquo;s great:\nNatural language planning Code generation Test creation Documentation Refactoring Use case: Plan and build features faster with AI assistance.\n5. Linear What it is: Modern issue tracking and project management.\nWhy it\u0026rsquo;s great:\nFast and keyboard-driven Beautiful UI Great for engineering teams GitHub integration Custom workflows Use case: Manage issues and projects more efficiently than Jira.\n6. Figma Dev Mode What it is: Developer-focused features in Figma.\nWhy it\u0026rsquo;s great:\nExtract CSS/React code Measure distances View specs Export assets Inspect designs Use case: Bridge the gap between design and development.\n7. Postman / Insomnia What it is: API development and testing tools.\nWhy it\u0026rsquo;s great:\nAPI testing Documentation Mock servers Team collaboration Automated testing Use case: Test and document APIs more effectively.\n8. Docker Desktop What it is: Container platform for development.\nWhy it\u0026rsquo;s great:\nConsistent environments Easy setup Resource management Extension marketplace Kubernetes support Use case: Standardize development environments across your team.\n9. Obsidian What it is: Knowledge management and note-taking app.\nWhy it\u0026rsquo;s great:\nMarkdown-based Graph view Plugin ecosystem Local-first Great for documentation Use case: Organize your knowledge, notes, and documentation.\nBonus: Browser Extensions 1. Refined GitHub Enhances GitHub with useful features.\n2. Wappalyzer Identifies technologies on websites.\n3. React Developer Tools Debug React applications.\n4. Vue DevTools Debug Vue applications.\n5. JSON Formatter Pretty-print JSON in browser.\nSetting Up Your Workflow 1. Choose Your Tools Pick tools that:\nSolve real problems Fit your workflow Work well together Have good documentation 2. Learn Keyboard Shortcuts Master shortcuts for:\nYour editor Terminal Browser OS navigation 3. Automate Repetitive Tasks Use:\nShell scripts Aliases Automation tools CI/CD pipelines 4. Customize Your Environment Configure:\nEditor settings Terminal prompt Browser setup OS preferences Productivity Tips 1. Use Snippets Create code snippets for:\nCommon patterns Boilerplate code Templates Reusable components 2. Master Your Editor Learn:\nMulti-cursor editing Find and replace Command palette Extensions Custom keybindings 3. Use Version Control Effectively Meaningful commit messages Branch strategies Code reviews Git aliases 4. Document as You Go Inline comments README files API documentation Code examples Measuring Productivity Track:\nTime saved Bugs prevented Code quality Team velocity Developer satisfaction Conclusion The best productivity tools:\nSave time: Automate repetitive tasks Reduce errors: Catch issues early Improve quality: Better code and processes Enhance collaboration: Better team workflows Make work enjoyable: Better developer experience Start with one tool, master it, then add more.\nDon\u0026rsquo;t try to adopt everything at once. Pick tools that solve your specific problems and integrate them gradually into your workflow.\nThe goal isn\u0026rsquo;t to use every tool—it\u0026rsquo;s to work smarter, not harder.\nHappy coding! 🚀\n","permalink":"https://pixcave.com/posts/developer-productivity-tools/","summary":"\u003cp\u003eHere are 9 developer productivity tools that can dramatically improve your workflow and save you hours every week.\u003c/p\u003e\n\u003ch2 id=\"1-warp-terminal\"\u003e1. Warp Terminal\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eWhat it is:\u003c/strong\u003e A modern, Rust-based terminal with AI assistance.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWhy it\u0026rsquo;s great:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAI command suggestions\u003c/li\u003e\n\u003cli\u003eSplit panes and tabs\u003c/li\u003e\n\u003cli\u003eCommand palette\u003c/li\u003e\n\u003cli\u003eBetter autocomplete\u003c/li\u003e\n\u003cli\u003eIntegrated workflows\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eUse case:\u003c/strong\u003e Replace your default terminal for a better development experience.\u003c/p\u003e\n\u003ch2 id=\"2-cursor-ai-editor\"\u003e2. Cursor AI Editor\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eWhat it is:\u003c/strong\u003e VS Code fork with built-in AI coding assistant.\u003c/p\u003e","title":"9 Developer Productivity Tools You Wish You Knew Sooner"},{"content":"Web design is constantly evolving. Here are the modern design styles every frontend developer should know in 2025.\n1. Glassmorphism Glassmorphism creates a frosted glass effect with:\nSemi-transparent backgrounds Backdrop blur filters Subtle borders Layered depth Implementation .glass-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); border-radius: 16px; } Use Cases Cards and modals Navigation bars Overlays Dashboard elements 2. Neumorphism Neumorphism (soft UI) creates a soft, extruded look:\nSubtle shadows Light and dark elements Minimal color palette 3D appearance Implementation .neumorphic { background: #e0e0e0; box-shadow: 9px 9px 16px rgba(163, 177, 198, 0.6), -9px -9px 16px rgba(255, 255, 255, 0.5); border-radius: 20px; } .neumorphic-inset { box-shadow: inset 9px 9px 16px rgba(163, 177, 198, 0.6), inset -9px -9px 16px rgba(255, 255, 255, 0.5); } Use Cases Buttons and controls Cards Input fields Toggle switches 3. Brutalism Brutalist design embraces:\nRaw, unpolished aesthetics Bold typography High contrast Asymmetric layouts Minimal styling Characteristics .brutalist { border: 4px solid #000; background: #fff; box-shadow: 8px 8px 0 #000; font-weight: 900; text-transform: uppercase; padding: 2rem; } Use Cases Portfolio sites Creative agencies Bold brand statements Experimental projects 4. Minimalism Minimalism focuses on:\nClean layouts Generous whitespace Limited color palette Essential elements only Clear typography Principles .minimal { max-width: 1200px; margin: 0 auto; padding: 4rem 2rem; } .minimal h1 { font-size: 3rem; font-weight: 300; letter-spacing: -0.02em; margin-bottom: 2rem; } Use Cases Corporate websites Blogs E-commerce Professional portfolios 5. Dark Mode Design Dark mode is now essential:\nReduced eye strain Better battery life (OLED) Modern aesthetic User preference Implementation :root { --bg-light: #ffffff; --text-light: #000000; --bg-dark: #1a1a1a; --text-dark: #ffffff; } @media (prefers-color-scheme: dark) { body { background: var(--bg-dark); color: var(--text-dark); } } [data-theme=\u0026#34;dark\u0026#34;] { background: var(--bg-dark); color: var(--text-dark); } Best Practices Test contrast ratios Adjust colors, not just invert Consider accent colors Provide toggle option 6. Micro-interactions Micro-interactions enhance UX:\nButton hover states Loading animations Success feedback Smooth transitions Examples .button { transition: all 0.3s ease; } .button:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); } .button:active { transform: translateY(0); } // Loading state function showLoading() { button.innerHTML = \u0026#39;\u0026lt;span class=\u0026#34;spinner\u0026#34;\u0026gt;\u0026lt;/span\u0026gt; Loading...\u0026#39;; button.disabled = true; } 7. Responsive Typography Fluid typography that adapts:\nClamp() for responsive sizes Viewport-based units Readable line heights Proper scaling Implementation h1 { font-size: clamp(2rem, 5vw, 4rem); line-height: 1.2; } p { font-size: clamp(1rem, 2vw, 1.25rem); line-height: 1.6; max-width: 65ch; } 8. Grid and Flexbox Layouts Modern layout techniques:\nCSS Grid for complex layouts Flexbox for component layouts Container queries Subgrid Grid Example .grid-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; padding: 2rem; } Flexbox Example .card { display: flex; flex-direction: column; justify-content: space-between; gap: 1rem; } 9. Custom Properties (CSS Variables) Dynamic theming and maintainability:\n:root { --primary-color: #007bff; --secondary-color: #6c757d; --spacing-unit: 1rem; --border-radius: 8px; } .button { background: var(--primary-color); padding: var(--spacing-unit); border-radius: var(--border-radius); } 10. Accessibility-First Design Designing for everyone:\nSemantic HTML ARIA labels Keyboard navigation Color contrast Screen reader support Checklist \u0026lt;!-- Semantic HTML --\u0026gt; \u0026lt;nav aria-label=\u0026#34;Main navigation\u0026#34;\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/\u0026#34; aria-current=\u0026#34;page\u0026#34;\u0026gt;Home\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;/nav\u0026gt; \u0026lt;!-- Accessible forms --\u0026gt; \u0026lt;label for=\u0026#34;email\u0026#34;\u0026gt;Email\u0026lt;/label\u0026gt; \u0026lt;input type=\u0026#34;email\u0026#34; id=\u0026#34;email\u0026#34; aria-required=\u0026#34;true\u0026#34; aria-describedby=\u0026#34;email-error\u0026#34; \u0026gt; \u0026lt;span id=\u0026#34;email-error\u0026#34; role=\u0026#34;alert\u0026#34;\u0026gt;\u0026lt;/span\u0026gt; 11. Performance-First Design Optimize for speed:\nLazy loading images Code splitting Critical CSS Optimized assets \u0026lt;!-- Lazy loading --\u0026gt; \u0026lt;img src=\u0026#34;image.jpg\u0026#34; loading=\u0026#34;lazy\u0026#34; alt=\u0026#34;Description\u0026#34; \u0026gt; \u0026lt;!-- Modern image formats --\u0026gt; \u0026lt;picture\u0026gt; \u0026lt;source srcset=\u0026#34;image.avif\u0026#34; type=\u0026#34;image/avif\u0026#34;\u0026gt; \u0026lt;source srcset=\u0026#34;image.webp\u0026#34; type=\u0026#34;image/webp\u0026#34;\u0026gt; \u0026lt;img src=\u0026#34;image.jpg\u0026#34; alt=\u0026#34;Description\u0026#34;\u0026gt; \u0026lt;/picture\u0026gt; 12. Motion and Animation Subtle animations enhance UX:\nFade in/out Slide transitions Scale effects Parallax scrolling @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .animate { animation: fadeIn 0.5s ease-out; } Best Practices 1. Consistency Use design systems Maintain style guides Follow patterns Document decisions 2. Performance Optimize assets Minimize animations Use efficient CSS Test on devices 3. Accessibility Test with screen readers Check color contrast Ensure keyboard navigation Validate HTML 4. Responsiveness Mobile-first approach Test on real devices Use flexible units Consider touch targets Tools and Resources Design Tools Figma Adobe XD Sketch Framer CSS Frameworks Tailwind CSS Bootstrap Material UI Chakra UI Animation Libraries Framer Motion GSAP Lottie Three.js Conclusion Modern web design in 2025 emphasizes:\nUser experience: Accessibility and performance Visual appeal: Modern aesthetics and trends Functionality: Purposeful design choices Technology: Leveraging modern CSS and JavaScript Stay current with:\nDesign trends CSS features Browser capabilities User expectations The best designs solve problems, not just look good.\nChoose styles that:\nServe your users Fit your brand Work on all devices Perform well Are accessible to everyone Happy designing! 🎨\n","permalink":"https://pixcave.com/posts/modern-web-design-styles-2025/","summary":"\u003cp\u003eWeb design is constantly evolving. Here are the modern design styles every frontend developer should know in 2025.\u003c/p\u003e\n\u003ch2 id=\"1-glassmorphism\"\u003e1. Glassmorphism\u003c/h2\u003e\n\u003cp\u003eGlassmorphism creates a frosted glass effect with:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSemi-transparent backgrounds\u003c/li\u003e\n\u003cli\u003eBackdrop blur filters\u003c/li\u003e\n\u003cli\u003eSubtle borders\u003c/li\u003e\n\u003cli\u003eLayered depth\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"implementation\"\u003eImplementation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003eglass-card\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ebackground\u003c/span\u003e: rgba(\u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0.1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  backdrop-filter: blur(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eborder\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003esolid\u003c/span\u003e rgba(\u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0.2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ebox-shadow\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e32\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e rgba(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0.1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eborder-radius\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-cases\"\u003eUse Cases\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eCards and modals\u003c/li\u003e\n\u003cli\u003eNavigation bars\u003c/li\u003e\n\u003cli\u003eOverlays\u003c/li\u003e\n\u003cli\u003eDashboard elements\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-neumorphism\"\u003e2. Neumorphism\u003c/h2\u003e\n\u003cp\u003eNeumorphism (soft UI) creates a soft, extruded look:\u003c/p\u003e","title":"Modern Web Design Styles Every Frontend Developer Must Know (2025 Guide)"},{"content":"What LLMs can\u0026rsquo;t learn from text — and why human-like understanding may require bodies, not bigger models.\nThe Fundamental Limitation Large Language Models (LLMs) have achieved remarkable success by learning from text. But there\u0026rsquo;s a fundamental gap: they lack sensorimotor experience.\nWhat is the Sensorimotor Gap? The sensorimotor gap refers to the difference between:\nTextual knowledge: What can be learned from reading Embodied knowledge: What requires physical interaction Examples Text can teach:\n\u0026ldquo;A cup is used for drinking\u0026rdquo; \u0026ldquo;Red means stop\u0026rdquo; \u0026ldquo;Gravity pulls objects down\u0026rdquo; But text cannot teach:\nThe weight of a cup in your hand The feeling of acceleration The texture of different materials Spatial relationships through movement Cause and effect through manipulation Why This Matters 1. Understanding vs. Knowledge LLMs can:\nGenerate text about concepts Answer questions about topics Explain relationships But they cannot:\nTruly understand physical causality Predict outcomes from first principles Generalize to novel situations Reason about space and time 2. The Grounding Problem Without sensorimotor experience:\nWords lack referents Concepts are abstract Knowledge is disconnected Understanding is shallow 3. Limitations in Reasoning LLMs struggle with:\nPhysical reasoning: Predicting object behavior Spatial reasoning: Understanding 3D relationships Temporal reasoning: Understanding cause and effect Causal reasoning: Identifying true causes What Text Can\u0026rsquo;t Convey Embodied Knowledge Proprioception:\nKnowing where your body is in space Understanding movement and balance Feeling muscle tension and effort Haptic Feedback:\nTexture and material properties Weight and resistance Temperature and pressure Spatial Understanding:\nDistance and scale Orientation and perspective Navigation and wayfinding Experiential Learning Trial and Error:\nLearning from mistakes Understanding consequences Developing intuition Cause and Effect:\nManipulating objects Observing outcomes Building mental models Social Interaction:\nReading body language Understanding tone and emotion Responding to feedback The Path Forward 1. Multimodal Models Combine text with:\nVision: Understanding visual information Audio: Processing sound and speech Video: Learning from motion Sensors: Getting real-world data 2. Embodied AI Robots that:\nInteract with the physical world Learn from manipulation Develop sensorimotor skills Build grounded understanding 3. Simulation Virtual environments where AI can:\nPractice physical interactions Learn from simulated physics Develop spatial reasoning Understand cause and effect 4. Hybrid Approaches Combine:\nText learning: Broad knowledge Embodied learning: Grounded understanding Simulation: Safe experimentation Human feedback: Guided learning Implications for AI Development Current Limitations We should recognize that:\nLLMs excel at language tasks But struggle with physical reasoning And lack true understanding Bigger models won\u0026rsquo;t solve this Future Directions Focus on:\nMultimodal learning: Beyond text Embodied systems: Physical interaction Causal reasoning: Understanding mechanisms Grounded knowledge: Connecting symbols to reality The Philosophical Question Can Understanding Exist Without Experience? Arguments for:\nMathematical truths exist independently Abstract concepts don\u0026rsquo;t require embodiment Symbolic reasoning can be sufficient Arguments against:\nUnderstanding requires grounding Concepts need referents Knowledge requires experience Meaning comes from interaction The Middle Ground Perhaps:\nSome understanding is possible from text But full understanding requires experience Different types of knowledge need different approaches Hybrid systems may be the answer Practical Implications For Developers When building AI systems:\nRecognize text-only limitations Consider multimodal approaches Use simulation when possible Combine different learning methods For Users When using AI:\nUnderstand its limitations Don\u0026rsquo;t expect physical reasoning Verify important claims Use AI as a tool, not a replacement Conclusion The sensorimotor gap highlights a fundamental limitation of text-only learning. While LLMs have achieved remarkable success, true understanding may require:\nEmbodied experience: Physical interaction with the world Multimodal learning: Beyond just text Causal reasoning: Understanding mechanisms Grounded knowledge: Connecting symbols to reality Bigger models won\u0026rsquo;t solve this. We need different approaches:\nEmbodied AI systems Multimodal learning Simulation environments Hybrid architectures The future of AI isn\u0026rsquo;t just bigger language models—it\u0026rsquo;s systems that can learn from experience, reason about the physical world, and develop true understanding through interaction.\nThis is the challenge—and opportunity—for the next generation of AI systems.\n","permalink":"https://pixcave.com/posts/llm-sensorimotor-gap/","summary":"\u003cp\u003eWhat LLMs can\u0026rsquo;t learn from text — and why human-like understanding may require bodies, not bigger models.\u003c/p\u003e\n\u003ch2 id=\"the-fundamental-limitation\"\u003eThe Fundamental Limitation\u003c/h2\u003e\n\u003cp\u003eLarge Language Models (LLMs) have achieved remarkable success by learning from text. But there\u0026rsquo;s a fundamental gap: \u003cstrong\u003ethey lack sensorimotor experience\u003c/strong\u003e.\u003c/p\u003e\n\u003ch2 id=\"what-is-the-sensorimotor-gap\"\u003eWhat is the Sensorimotor Gap?\u003c/h2\u003e\n\u003cp\u003eThe sensorimotor gap refers to the difference between:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eTextual knowledge\u003c/strong\u003e: What can be learned from reading\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEmbodied knowledge\u003c/strong\u003e: What requires physical interaction\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"examples\"\u003eExamples\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eText can teach:\u003c/strong\u003e\u003c/p\u003e","title":"The Sensorimotor Gap: What LLMs Can't Learn from Text"},{"content":"Three weeks ago, I had 191,000 tokens in my upcoming tactical survival roguelite game\u0026rsquo;s codebase. Today, I have 104,000 tokens: a 45% reduction.\nHere\u0026rsquo;s what I learned about AI-generated code and why removing it made my game better.\nThe Problem with AI-Generated Code What is \u0026ldquo;AI Slop\u0026rdquo;? AI slop refers to code that:\nWorks but is unnecessarily verbose Lacks clear intent and purpose Contains redundant patterns Has inconsistent style Includes unnecessary abstractions Lacks proper error handling Has poor performance characteristics Why Does It Happen? AI tools like ChatGPT and GitHub Copilot:\nGenerate code that \u0026ldquo;works\u0026rdquo; but isn\u0026rsquo;t optimal Don\u0026rsquo;t understand the broader codebase context Tend to over-engineer solutions Copy patterns without understanding them Generate boilerplate unnecessarily My Experience Before: The AI-Generated Mess // AI-generated code public class PlayerHealthManager : MonoBehaviour { [SerializeField] private float currentHealth; [SerializeField] private float maximumHealth; [SerializeField] private bool isDead; public event Action\u0026lt;float\u0026gt; OnHealthChanged; public event Action OnPlayerDied; public void TakeDamage(float damageAmount) { if (damageAmount \u0026gt; 0 \u0026amp;\u0026amp; !isDead) { currentHealth = Mathf.Max(0, currentHealth - damageAmount); OnHealthChanged?.Invoke(currentHealth); if (currentHealth \u0026lt;= 0) { isDead = true; OnPlayerDied?.Invoke(); } } } public void Heal(float healAmount) { if (healAmount \u0026gt; 0 \u0026amp;\u0026amp; !isDead) { currentHealth = Mathf.Min(maximumHealth, currentHealth + healAmount); OnHealthChanged?.Invoke(currentHealth); } } // ... 50 more lines of similar code } After: Clean, Purposeful Code // Refactored code public class Health : MonoBehaviour { [SerializeField] float max = 100; float current; public float Value =\u0026gt; current; public float Percent =\u0026gt; current / max; public void Damage(float amount) =\u0026gt; Modify(-amount); public void Heal(float amount) =\u0026gt; Modify(amount); void Modify(float amount) { current = Mathf.Clamp(current + amount, 0, max); if (current == 0) Die(); } void Die() =\u0026gt; Destroy(gameObject); } Result: 50 lines → 15 lines, clearer intent, better performance.\nThe Refactoring Process Step 1: Identify AI Patterns Look for:\nOverly descriptive names (PlayerHealthManager vs Health) Unnecessary events and callbacks Redundant null checks Verbose conditionals Unused abstractions Step 2: Simplify Remove unnecessary abstractions Consolidate similar methods Use language features (properties, expressions) Eliminate redundant checks Simplify control flow Step 3: Test Thoroughly Write tests before refactoring Run tests after each change Verify behavior is identical Check performance improvements Step 4: Measure Impact Track:\nLines of code Cyclomatic complexity Performance metrics Build times Memory usage Key Improvements 1. Reduced Complexity Before:\n15 classes for player systems Multiple managers and controllers Complex event systems Deep inheritance hierarchies After:\n8 focused components Direct method calls Simple data flow Composition over inheritance 2. Better Performance Fewer allocations: Removed unnecessary object creation Less indirection: Direct calls instead of events Smaller memory footprint: Removed redundant data Faster execution: Simpler code paths 3. Improved Maintainability Clearer intent: Code does what it says Easier to understand: Less cognitive load Faster to modify: Simpler structure Better debugging: Straightforward execution flow 4. Reduced Bugs Fewer edge cases: Simpler code has fewer bugs Easier to test: Less mocking and setup Clearer logic: Harder to introduce bugs Better error handling: Focused error paths Lessons Learned 1. AI is a Starting Point, Not an Endpoint Use AI to:\nGenerate initial structure Explore different approaches Get unstuck on syntax Then:\nReview and refactor Simplify and optimize Make it your own 2. Simplicity Wins The best code is:\nSimple: Easy to understand Focused: Does one thing well Direct: No unnecessary indirection Clear: Intent is obvious 3. Code Review is Essential Always review AI-generated code:\nDoes it solve the right problem? Is it the simplest solution? Can it be improved? Does it fit the codebase? 4. Measure Everything Track metrics to:\nIdentify improvements Justify refactoring Prevent regressions Guide decisions Best Practices for Using AI Do: Use AI for exploration and learning Review all AI-generated code Refactor to fit your style Test thoroughly Document decisions Don\u0026rsquo;t: Blindly accept AI suggestions Use AI output without review Skip testing Ignore code quality Assume AI knows best The Results After removing AI slop:\n45% less code: 191k → 104k tokens 30% faster builds: Less code to compile 20% better performance: Simpler execution 50% fewer bugs: Less complexity 100% more maintainable: Clearer code Conclusion AI tools are powerful, but they\u0026rsquo;re not a substitute for:\nGood judgment: Knowing when code is good enough Code review: Catching issues before they spread Refactoring: Making code better over time Testing: Ensuring correctness Experience: Understanding what works The best code is written by humans, reviewed by humans, and maintained by humans.\nAI can help, but it can\u0026rsquo;t replace thoughtful engineering. Use it wisely, review it carefully, and always make it better.\nYour codebase—and your future self—will thank you.\n","permalink":"https://pixcave.com/posts/removing-ai-generated-code/","summary":"\u003cp\u003eThree weeks ago, I had 191,000 tokens in my upcoming tactical survival roguelite game\u0026rsquo;s codebase. Today, I have 104,000 tokens: a \u003cstrong\u003e45% reduction\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eHere\u0026rsquo;s what I learned about AI-generated code and why removing it made my game better.\u003c/p\u003e\n\u003ch2 id=\"the-problem-with-ai-generated-code\"\u003eThe Problem with AI-Generated Code\u003c/h2\u003e\n\u003ch3 id=\"what-is-ai-slop\"\u003eWhat is \u0026ldquo;AI Slop\u0026rdquo;?\u003c/h3\u003e\n\u003cp\u003eAI slop refers to code that:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWorks but is unnecessarily verbose\u003c/li\u003e\n\u003cli\u003eLacks clear intent and purpose\u003c/li\u003e\n\u003cli\u003eContains redundant patterns\u003c/li\u003e\n\u003cli\u003eHas inconsistent style\u003c/li\u003e\n\u003cli\u003eIncludes unnecessary abstractions\u003c/li\u003e\n\u003cli\u003eLacks proper error handling\u003c/li\u003e\n\u003cli\u003eHas poor performance characteristics\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"why-does-it-happen\"\u003eWhy Does It Happen?\u003c/h3\u003e\n\u003cp\u003eAI tools like ChatGPT and GitHub Copilot:\u003c/p\u003e","title":"How I Scrubbed 100% of the AI Slop From My Game \u0026 Cut Code by 45%"},{"content":"And I pay for it literally. You should know this if you use AI-generated content for business purposes.\nThe Common Assumption Most developers and businesses assume that:\nAI-generated content is free to use You own what AI creates for you There are no licensing restrictions It\u0026rsquo;s safe to use commercially This is incorrect.\nThe Legal Reality Copyright and Ownership AI-generated content raises complex copyright questions:\nWho owns AI output?\nThe AI company? The user who prompted it? No one (public domain)? Is AI output copyrightable?\nIn many jurisdictions, works created by non-humans aren\u0026rsquo;t copyrightable This means AI output might be in the public domain But this varies by country and is still being litigated Terms of Service Most AI services have specific terms:\nOpenAI (ChatGPT, DALL-E):\nYou own the output But you\u0026rsquo;re responsible for ensuring it doesn\u0026rsquo;t infringe on others\u0026rsquo; rights You can\u0026rsquo;t use output to train competing models Midjourney:\nYou own the output if you\u0026rsquo;re a paid subscriber Free users have limited commercial rights Stable Diffusion:\nOpen source model But training data may have copyright issues Google (Gemini):\nYou own the output But subject to Google\u0026rsquo;s terms of service The Hidden Costs 1. Legal Risk Using AI-generated content commercially can expose you to:\nCopyright infringement: If AI output resembles copyrighted material Trademark issues: If AI generates trademarked names/logos Right of publicity: If AI generates recognizable people Data privacy: If AI output contains personal information 2. Quality and Liability Inaccurate information: You\u0026rsquo;re liable for AI mistakes Bias and discrimination: AI can perpetuate harmful biases Security vulnerabilities: AI-generated code may have security issues 3. Compliance Costs You may need:\nLegal review of AI-generated content Compliance with industry regulations (GDPR, HIPAA, etc.) Insurance for AI-related risks Documentation and audit trails Real-World Scenarios Scenario 1: Marketing Content Problem: You use ChatGPT to generate marketing copy for your website.\nRisks:\nCopyright infringement if output resembles existing content Trademark issues if AI uses protected terms False advertising if AI makes unsubstantiated claims Solution:\nReview all AI-generated content Fact-check claims Ensure originality Consider legal review for high-stakes content Scenario 2: Code Generation Problem: You use GitHub Copilot or ChatGPT to write code.\nRisks:\nCode may be copied from open-source projects with restrictive licenses Security vulnerabilities in generated code Patent infringement if code implements patented algorithms Solution:\nReview all generated code Run security scans Check for license compatibility Document AI assistance in code comments Scenario 3: Images and Media Problem: You use DALL-E or Midjourney to create images for your product.\nRisks:\nOutput may resemble copyrighted artwork Trademark issues with logos or brand elements Right of publicity if people are recognizable Solution:\nReview images for similarity to existing works Check for trademark conflicts Consider licensing stock images instead Get legal review for commercial use Best Practices 1. Read the Terms of Service Always read and understand:\nWhat rights you have to the output What restrictions apply What liabilities you assume How the service can use your inputs 2. Implement Review Processes Human review: Never use AI output without human oversight Legal review: For high-stakes content, get legal input Quality checks: Verify accuracy and appropriateness Originality checks: Ensure content doesn\u0026rsquo;t infringe 3. Document Everything Keep records of:\nWhat AI tools you used What prompts you provided What output you received How you reviewed and modified it When and where you used it 4. Consider Alternatives Sometimes it\u0026rsquo;s better to:\nHire human creators Use licensed stock content Create original content yourself Use AI for inspiration, not final output 5. Get Insurance Consider:\nProfessional liability insurance Errors and omissions coverage Cyber liability insurance AI-specific coverage (if available) The Regulatory Landscape Laws are evolving:\nEU AI Act: Regulates AI use in Europe US Executive Order: Sets AI safety standards China\u0026rsquo;s AI Regulations: Strict rules on AI-generated content Copyright Office: Clarifying AI copyright issues Stay informed about:\nNew regulations in your jurisdiction Court decisions on AI copyright Industry-specific requirements Best practices from legal experts What You Should Do Now Immediate Actions Audit your AI usage: What AI tools are you using? Review terms of service: What are your rights and obligations? Assess risks: What could go wrong? Implement safeguards: How can you reduce risk? Long-Term Strategy Develop policies: Create guidelines for AI use Train your team: Educate on legal and ethical considerations Monitor changes: Stay updated on legal developments Consult experts: Get legal advice when needed Conclusion AI-generated content isn\u0026rsquo;t free—it comes with:\nLegal risks Compliance costs Quality concerns Liability exposure The cost isn\u0026rsquo;t just monetary; it\u0026rsquo;s also:\nTime for review and compliance Risk of legal issues Potential damage to your reputation Lost opportunities from overly cautious use The key is informed, responsible use. Understand the risks, implement safeguards, and use AI as a tool to enhance—not replace—human judgment and creativity.\nDon\u0026rsquo;t learn this lesson the hard way. Start protecting yourself and your business today.\n","permalink":"https://pixcave.com/posts/ai-output-legal-considerations/","summary":"\u003cp\u003e\u003cstrong\u003eAnd I pay for it \u003cem\u003eliterally\u003c/em\u003e.\u003c/strong\u003e You should know this if you use AI-generated content for business purposes.\u003c/p\u003e\n\u003ch2 id=\"the-common-assumption\"\u003eThe Common Assumption\u003c/h2\u003e\n\u003cp\u003eMost developers and businesses assume that:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAI-generated content is free to use\u003c/li\u003e\n\u003cli\u003eYou own what AI creates for you\u003c/li\u003e\n\u003cli\u003eThere are no licensing restrictions\u003c/li\u003e\n\u003cli\u003eIt\u0026rsquo;s safe to use commercially\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eThis is incorrect.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"the-legal-reality\"\u003eThe Legal Reality\u003c/h2\u003e\n\u003ch3 id=\"copyright-and-ownership\"\u003eCopyright and Ownership\u003c/h3\u003e\n\u003cp\u003eAI-generated content raises complex copyright questions:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eWho owns AI output?\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe AI company?\u003c/li\u003e\n\u003cli\u003eThe user who prompted it?\u003c/li\u003e\n\u003cli\u003eNo one (public domain)?\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eIs AI output copyrightable?\u003c/strong\u003e\u003c/p\u003e","title":"I Thought AI Output Was Free to Use. I Was Wrong."},{"content":"Spoiler alert: yes. But not for the reasons you might think.\nThe Common Misconception Many engineers believe that presentation skills are only important for:\nManagers and team leads Sales engineers Conference speakers People in \u0026ldquo;non-technical\u0026rdquo; roles But the reality is different.\nWhy Presentation Skills Matter for Engineers 1. Technical Communication As an engineer, you constantly need to:\nExplain complex technical concepts to non-technical stakeholders Present architecture decisions to your team Defend your technical choices in code reviews Document your work effectively All of these require presentation skills.\n2. Career Advancement Strong presentation skills directly impact your career:\nCode Reviews: Clear explanations lead to better feedback Design Reviews: Well-presented designs get approved faster Performance Reviews: You can better articulate your contributions Promotions: Leadership roles require communication skills 3. Influence and Impact Your ideas are only as good as your ability to communicate them:\n// Bad presentation \u0026#34;Uh, I think we should, like, maybe use Redis here because, you know, it\u0026#39;s faster and stuff.\u0026#34; // Good presentation \u0026#34;Based on our load testing, Redis would reduce our cache latency by 60% and handle 10x more concurrent requests. Here\u0026#39;s the data...\u0026#34; 4. Team Collaboration Effective presentations improve team dynamics:\nStand-ups: Clear updates help the team stay aligned Retrospectives: Well-structured feedback drives improvement Knowledge Sharing: Good presentations make learning easier What Makes a Good Technical Presentation? Structure Problem: What are we solving? Context: Why does it matter? Solution: What\u0026rsquo;s the approach? Trade-offs: What are the costs and benefits? Next Steps: What do we do now? Clarity Use simple language when possible Explain acronyms and jargon Use visuals (diagrams, charts, code examples) Tell a story, not just facts Engagement Ask questions Use examples Relate to your audience\u0026rsquo;s experience Be concise Practical Tips for Engineers 1. Start Small You don\u0026rsquo;t need to give conference talks. Start with:\nTeam meetings Code review explanations Documentation Internal tech talks 2. Practice Like coding, presentation skills improve with practice:\nRecord yourself explaining a concept Get feedback from peers Join a local meetup or Toastmasters Present at internal tech talks 3. Use Your Technical Skills Engineers have unique advantages:\nCreate diagrams and visualizations Build demos and prototypes Use data to support your points Write clear, structured documentation 4. Learn from Others Watch great technical presenters:\nConference talks (React Conf, PyCon, etc.) YouTube channels (Fireship, Traversy Media) Internal presentations at your company Common Mistakes to Avoid 1. Too Much Detail Don\u0026rsquo;t overwhelm your audience with implementation details. Focus on:\nThe problem and why it matters High-level approach Key trade-offs Impact and outcomes 2. Assuming Knowledge Don\u0026rsquo;t assume everyone knows:\nYour tech stack Industry jargon Previous context Your thought process 3. No Clear Structure A rambling presentation loses your audience. Always have:\nA clear beginning (problem/context) A middle (solution/approach) An end (next steps/outcomes) 4. Ignoring Your Audience Pay attention to:\nQuestions and confusion Body language Engagement levels Time constraints Real-World Examples Architecture Decision Bad: \u0026ldquo;We should use microservices.\u0026rdquo;\nGood: \u0026ldquo;Our monolithic application is becoming a bottleneck. We\u0026rsquo;re seeing deployment conflicts, scaling issues, and team coordination problems. Moving to microservices would allow independent deployments and scaling, though it adds complexity. Here\u0026rsquo;s our migration plan\u0026hellip;\u0026rdquo;\nBug Explanation Bad: \u0026ldquo;The bug is fixed.\u0026rdquo;\nGood: \u0026ldquo;The issue was a race condition in our cache invalidation. When multiple requests updated the same resource, the cache wasn\u0026rsquo;t properly synchronized. I\u0026rsquo;ve added a distributed lock to prevent concurrent updates. Here\u0026rsquo;s the fix and test cases\u0026hellip;\u0026rdquo;\nThe Bottom Line Presentation skills aren\u0026rsquo;t about being a \u0026ldquo;people person\u0026rdquo; or giving TED talks. They\u0026rsquo;re about:\nClear communication: Making complex ideas understandable Influence: Getting your ideas heard and adopted Collaboration: Working effectively with your team Career growth: Opening doors to new opportunities As an engineer, your code speaks for itself, but your ability to explain and advocate for your work determines your impact and career trajectory.\nStart practicing today. Your future self will thank you.\n","permalink":"https://pixcave.com/posts/software-engineers-presentation-skills/","summary":"\u003cp\u003e\u003cstrong\u003eSpoiler alert: yes.\u003c/strong\u003e But not for the reasons you might think.\u003c/p\u003e\n\u003ch2 id=\"the-common-misconception\"\u003eThe Common Misconception\u003c/h2\u003e\n\u003cp\u003eMany engineers believe that presentation skills are only important for:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eManagers and team leads\u003c/li\u003e\n\u003cli\u003eSales engineers\u003c/li\u003e\n\u003cli\u003eConference speakers\u003c/li\u003e\n\u003cli\u003ePeople in \u0026ldquo;non-technical\u0026rdquo; roles\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBut the reality is different.\u003c/p\u003e\n\u003ch2 id=\"why-presentation-skills-matter-for-engineers\"\u003eWhy Presentation Skills Matter for Engineers\u003c/h2\u003e\n\u003ch3 id=\"1-technical-communication\"\u003e1. Technical Communication\u003c/h3\u003e\n\u003cp\u003eAs an engineer, you constantly need to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eExplain complex technical concepts to non-technical stakeholders\u003c/li\u003e\n\u003cli\u003ePresent architecture decisions to your team\u003c/li\u003e\n\u003cli\u003eDefend your technical choices in code reviews\u003c/li\u003e\n\u003cli\u003eDocument your work effectively\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAll of these require presentation skills.\u003c/p\u003e","title":"Should Software Engineers Have Good Presentation Skills?"},{"content":"Kubernetes is powerful, but it\u0026rsquo;s also complex. This is my journey of trying to build a \u0026ldquo;simple\u0026rdquo; Kubernetes stack and the lessons learned along the way.\nThe Goal I wanted to create a simple, maintainable Kubernetes setup for a small to medium-sized application. The requirements were:\nEasy to understand and maintain Cost-effective Scalable when needed Developer-friendly What I Started With Initial Stack Kubernetes: EKS (AWS) Ingress: NGINX Ingress Controller Database: Managed PostgreSQL (RDS) Monitoring: Prometheus + Grafana Logging: ELK Stack CI/CD: GitLab CI The Reality Check Complexity Crept In What started as \u0026ldquo;simple\u0026rdquo; quickly became complex:\nNetworking: VPCs, subnets, security groups, load balancers Storage: Persistent volumes, storage classes, backups Secrets Management: Kubernetes secrets, external secret operators Service Mesh: Considered Istio, then Linkerd, then nothing Observability: Multiple tools, dashboards, alerts Cost Analysis After 3 months:\nEKS cluster: $73/month Worker nodes: $150/month Load balancer: $20/month RDS: $100/month Monitoring tools: $50/month Total: ~$400/month For a small application, this was overkill.\nThe Simplification Journey Phase 1: Move to Managed Kubernetes Switched to DigitalOcean Kubernetes:\nSimpler setup Lower costs (~$50/month for basic cluster) Better developer experience Still Kubernetes, but less complexity Phase 2: Simplify Observability Replaced Prometheus + Grafana + ELK with:\nDatadog: All-in-one monitoring (free tier available) Loki: Lightweight logging (replaces ELK) Phase 3: Use Helm Charts Standardized deployments with Helm:\n# values.yaml replicaCount: 2 image: repository: myapp tag: latest service: type: ClusterIP port: 80 ingress: enabled: true hosts: - host: myapp.com Phase 4: Infrastructure as Code Everything in Terraform:\nresource \u0026#34;digitalocean_kubernetes_cluster\u0026#34; \u0026#34;main\u0026#34; { name = \u0026#34;myapp-cluster\u0026#34; region = \u0026#34;nyc1\u0026#34; version = \u0026#34;1.29.0-do.0\u0026#34; node_pool { name = \u0026#34;worker-pool\u0026#34; size = \u0026#34;s-2vcpu-4gb\u0026#34; node_count = 2 } } Lessons Learned 1. Start Simple, Scale When Needed Don\u0026rsquo;t over-engineer from the start:\nStart with basic Kubernetes Add complexity only when you need it Use managed services when possible 2. Cost Matters For small applications:\nConsider simpler alternatives (Docker Compose, Railway, Render) Use managed Kubernetes (DigitalOcean, Linode) over cloud providers Monitor costs from day one 3. Developer Experience Make it easy for your team:\nUse Helm charts for consistency Document everything Provide local development setup Use tools like Skaffold or Tilt 4. Observability is Important, But\u0026hellip; You don\u0026rsquo;t need everything:\nStart with basic logging Add metrics when needed Use managed solutions when possible The Final Stack Simplified Architecture ┌─────────────────┐ │ Load Balancer │ └────────┬────────┘ │ ┌────────▼────────┐ │ Ingress (NGINX)│ └────────┬────────┘ │ ┌────────▼────────┐ │ Kubernetes │ │ - App Pods │ │ - Redis │ └────────┬────────┘ │ ┌────────▼────────┐ │ Managed DB │ └─────────────────┘ Tools Kubernetes: DigitalOcean Kubernetes Ingress: NGINX Ingress Controller Database: Managed PostgreSQL Monitoring: Datadog (free tier) CI/CD: GitHub Actions IaC: Terraform Monthly Cost: ~$150 When to Use Kubernetes Use Kubernetes when:\nYou have multiple services You need auto-scaling You have a dedicated DevOps team You\u0026rsquo;re running at scale Consider alternatives when:\nSingle application Small team Limited budget Simple requirements Alternatives to Consider For Small Applications Docker Compose: Simple, local development Railway: Deploy with git push Render: Managed platform Fly.io: Global deployment For Medium Applications DigitalOcean App Platform: Managed PaaS Heroku: Classic PaaS AWS App Runner: Serverless containers Conclusion Kubernetes is powerful, but it\u0026rsquo;s not always the right choice. My \u0026ldquo;simple\u0026rdquo; stack taught me:\nStart simple: Don\u0026rsquo;t over-engineer Monitor costs: They add up quickly Use managed services: Save time and complexity Document everything: Future you will thank you Know when to simplify: Sometimes less is more The best infrastructure is the one that:\nMeets your needs Stays within budget Your team can maintain Scales when needed Sometimes, that\u0026rsquo;s not Kubernetes. And that\u0026rsquo;s okay.\n","permalink":"https://pixcave.com/posts/understanding-kubernetes-simple-stack/","summary":"\u003cp\u003eKubernetes is powerful, but it\u0026rsquo;s also complex. This is my journey of trying to build a \u0026ldquo;simple\u0026rdquo; Kubernetes stack and the lessons learned along the way.\u003c/p\u003e\n\u003ch2 id=\"the-goal\"\u003eThe Goal\u003c/h2\u003e\n\u003cp\u003eI wanted to create a simple, maintainable Kubernetes setup for a small to medium-sized application. The requirements were:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEasy to understand and maintain\u003c/li\u003e\n\u003cli\u003eCost-effective\u003c/li\u003e\n\u003cli\u003eScalable when needed\u003c/li\u003e\n\u003cli\u003eDeveloper-friendly\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"what-i-started-with\"\u003eWhat I Started With\u003c/h2\u003e\n\u003ch3 id=\"initial-stack\"\u003eInitial Stack\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eKubernetes\u003c/strong\u003e: EKS (AWS)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIngress\u003c/strong\u003e: NGINX Ingress Controller\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDatabase\u003c/strong\u003e: Managed PostgreSQL (RDS)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitoring\u003c/strong\u003e: Prometheus + Grafana\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLogging\u003c/strong\u003e: ELK Stack\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCI/CD\u003c/strong\u003e: GitLab CI\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"the-reality-check\"\u003eThe Reality Check\u003c/h2\u003e\n\u003ch3 id=\"complexity-crept-in\"\u003eComplexity Crept In\u003c/h3\u003e\n\u003cp\u003eWhat started as \u0026ldquo;simple\u0026rdquo; quickly became complex:\u003c/p\u003e","title":"Reinventing Kubernetes in 2025: A Post-Mortem of My 'Simple' Stack"},{"content":"Deploying FastAPI applications to production on a VPS requires careful configuration. This step-by-step guide will walk you through the entire process.\nPrerequisites A VPS with Ubuntu 20.04 or later Domain name (optional but recommended) Basic knowledge of Linux commands Step 1: Server Setup Update System sudo apt update sudo apt upgrade -y Install Python and Dependencies sudo apt install python3.9 python3-pip python3-venv nginx supervisor -y Step 2: Create Application Directory mkdir -p /var/www/myapp cd /var/www/myapp Create Virtual Environment python3 -m venv venv source venv/bin/activate Step 3: Deploy Your Application Install Dependencies pip install fastapi uvicorn[standard] gunicorn Create Application File # main.py from fastapi import FastAPI app = FastAPI() @app.get(\u0026#34;/\u0026#34;) def read_root(): return {\u0026#34;Hello\u0026#34;: \u0026#34;World\u0026#34;} @app.get(\u0026#34;/health\u0026#34;) def health_check(): return {\u0026#34;status\u0026#34;: \u0026#34;healthy\u0026#34;} Step 4: Configure Gunicorn Create gunicorn_config.py:\n# gunicorn_config.py bind = \u0026#34;127.0.0.1:8000\u0026#34; workers = 4 worker_class = \u0026#34;uvicorn.workers.UvicornWorker\u0026#34; timeout = 120 keepalive = 5 Step 5: Setup Supervisor Create /etc/supervisor/conf.d/myapp.conf:\n[program:myapp] command=/var/www/myapp/venv/bin/gunicorn -c /var/www/myapp/gunicorn_config.py main:app directory=/var/www/myapp user=www-data autostart=true autorestart=true redirect_stderr=true stdout_logfile=/var/log/myapp.log Start the service:\nsudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start myapp Step 6: Configure Nginx Create /etc/nginx/sites-available/myapp:\nserver { listen 80; server_name yourdomain.com; location / { proxy_pass http://127.0.0.1:8000; 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; } } Enable the site:\nsudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx Step 7: Setup SSL with Let\u0026rsquo;s Encrypt sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d yourdomain.com Step 8: Security Hardening Firewall Configuration sudo ufw allow 22 sudo ufw allow 80 sudo ufw allow 443 sudo ufw enable Environment Variables Create .env file:\n# .env DATABASE_URL=postgresql://user:pass@localhost/dbname SECRET_KEY=your-secret-key-here Load in application:\nfrom dotenv import load_dotenv import os load_dotenv() DATABASE_URL = os.getenv(\u0026#34;DATABASE_URL\u0026#34;) SECRET_KEY = os.getenv(\u0026#34;SECRET_KEY\u0026#34;) Step 9: Monitoring and Logging Setup Log Rotation Create /etc/logrotate.d/myapp:\n/var/log/myapp.log { daily rotate 14 compress delaycompress notifempty create 0640 www-data www-data sharedscripts } Health Check Endpoint Already included in the application, monitor with:\ncurl http://localhost:8000/health Step 10: Performance Optimization Increase Worker Processes Adjust in gunicorn_config.py:\nworkers = (2 * CPU_COUNT) + 1 Enable Caching from fastapi_cache import FastAPICache from fastapi_cache.backends.redis import RedisBackend @app.on_event(\u0026#34;startup\u0026#34;) async def startup(): redis = aioredis.from_url(\u0026#34;redis://localhost\u0026#34;) FastAPICache.init(RedisBackend(redis), prefix=\u0026#34;myapp-cache\u0026#34;) Troubleshooting Check Application Logs sudo tail -f /var/log/myapp.log Check Supervisor Status sudo supervisorctl status myapp Restart Services sudo supervisorctl restart myapp sudo systemctl restart nginx Conclusion Following these steps will give you a production-ready FastAPI deployment on a VPS. Remember to:\nKeep your dependencies updated Monitor application logs regularly Set up automated backups Use environment variables for secrets Enable SSL/TLS encryption Configure proper firewall rules Your FastAPI application is now running in production!\n","permalink":"https://pixcave.com/posts/fastapi-production-deployment/","summary":"\u003cp\u003eDeploying FastAPI applications to production on a VPS requires careful configuration. This step-by-step guide will walk you through the entire process.\u003c/p\u003e\n\u003ch2 id=\"prerequisites\"\u003ePrerequisites\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eA VPS with Ubuntu 20.04 or later\u003c/li\u003e\n\u003cli\u003eDomain name (optional but recommended)\u003c/li\u003e\n\u003cli\u003eBasic knowledge of Linux commands\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"step-1-server-setup\"\u003eStep 1: Server Setup\u003c/h2\u003e\n\u003ch3 id=\"update-system\"\u003eUpdate System\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt upgrade -y\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"install-python-and-dependencies\"\u003eInstall Python and Dependencies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt install python3.9 python3-pip python3-venv nginx supervisor -y\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"step-2-create-application-directory\"\u003eStep 2: Create Application Directory\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p /var/www/myapp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /var/www/myapp\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"create-virtual-environment\"\u003eCreate Virtual Environment\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython3 -m venv venv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esource venv/bin/activate\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"step-3-deploy-your-application\"\u003eStep 3: Deploy Your Application\u003c/h2\u003e\n\u003ch3 id=\"install-dependencies\"\u003eInstall Dependencies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install fastapi uvicorn\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003estandard\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e gunicorn\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"create-application-file\"\u003eCreate Application File\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# main.py\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e fastapi \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e FastAPI\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e FastAPI()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@app.get\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eread_root\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e {\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;World\u0026#34;\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@app.get\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/health\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehealth_check\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e {\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;status\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;healthy\u0026#34;\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"step-4-configure-gunicorn\"\u003eStep 4: Configure Gunicorn\u003c/h2\u003e\n\u003cp\u003eCreate \u003ccode\u003egunicorn_config.py\u003c/code\u003e:\u003c/p\u003e","title":"Running FastAPI in Production on a VPS: Step-by-Step Guide"},{"content":"Vue is introducing support for declarative UI syntax, bringing it closer to mobile development patterns seen in Kotlin and Swift. This new approach moves away from traditional HTML templates, offering a more modern, type-safe way to build user interfaces.\nThe Evolution Traditional Vue templates use HTML:\n\u0026lt;template\u0026gt; \u0026lt;div class=\u0026#34;container\u0026#34;\u0026gt; \u0026lt;h1\u0026gt;{{ title }}\u0026lt;/h1\u0026gt; \u0026lt;button @click=\u0026#34;handleClick\u0026#34;\u0026gt;Click me\u0026lt;/button\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/template\u0026gt; The new declarative syntax is more similar to SwiftUI or Jetpack Compose:\n\u0026lt;script setup\u0026gt; import { View, Text, Button } from \u0026#34;vue-declarative\u0026#34;; const title = ref(\u0026#34;Hello World\u0026#34;); function handleClick() { console.log(\u0026#34;Clicked!\u0026#34;); } \u0026lt;/script\u0026gt; \u0026lt;template\u0026gt; \u0026lt;View class=\u0026#34;container\u0026#34;\u0026gt; \u0026lt;Text\u0026gt;{{ title }}\u0026lt;/Text\u0026gt; \u0026lt;Button onPress=\u0026#34;{handleClick}\u0026#34;\u0026gt;Click me\u0026lt;/Button\u0026gt; \u0026lt;/View\u0026gt; \u0026lt;/template\u0026gt; Key Benefits 1. Type Safety The declarative syntax provides better TypeScript support:\n\u0026lt;View\u0026gt; \u0026lt;Text fontSize={16} // TypeScript knows this is a number color=\u0026#34;blue\u0026#34; // TypeScript validates color values \u0026gt; Hello \u0026lt;/Text\u0026gt; \u0026lt;/View\u0026gt; 2. Component Composition Easier component composition similar to React or SwiftUI:\n\u0026lt;script setup\u0026gt; import { View, Text, Image } from \u0026#34;vue-declarative\u0026#34;; const Card = ({ title, image }) =\u0026gt; ( \u0026lt;View class=\u0026#34;card\u0026#34;\u0026gt; \u0026lt;Image src={image} /\u0026gt; \u0026lt;Text\u0026gt;{title}\u0026lt;/Text\u0026gt; \u0026lt;/View\u0026gt; ); \u0026lt;/script\u0026gt; 3. Better Mobile Support The syntax is more aligned with mobile development patterns, making it easier to share code between web and mobile:\n// Works similarly on web and mobile \u0026lt;View\u0026gt; \u0026lt;Text\u0026gt;Cross-platform component\u0026lt;/Text\u0026gt; \u0026lt;/View\u0026gt; Comparison with Other Frameworks SwiftUI (iOS) VStack { Text(\u0026#34;Hello\u0026#34;) Button(\u0026#34;Click\u0026#34;) { handleClick() } } Jetpack Compose (Android) Column { Text(\u0026#34;Hello\u0026#34;) Button(onClick = { handleClick() }) { Text(\u0026#34;Click\u0026#34;) } } New Vue Syntax \u0026lt;View\u0026gt; \u0026lt;Text\u0026gt;Hello\u0026lt;/Text\u0026gt; \u0026lt;Button onPress={handleClick}\u0026gt;Click\u0026lt;/Button\u0026gt; \u0026lt;/View\u0026gt; Migration Path Vue provides a gradual migration path:\nStart with new components: Use declarative syntax for new components Gradual conversion: Convert existing components over time Coexistence: Both syntaxes can coexist in the same project Example: Building a Todo App Traditional Vue \u0026lt;template\u0026gt; \u0026lt;div class=\u0026#34;todo-app\u0026#34;\u0026gt; \u0026lt;input v-model=\u0026#34;newTodo\u0026#34; @keyup.enter=\u0026#34;addTodo\u0026#34; /\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li v-for=\u0026#34;todo in todos\u0026#34; :key=\u0026#34;todo.id\u0026#34;\u0026gt; {{ todo.text }} \u0026lt;button @click=\u0026#34;removeTodo(todo.id)\u0026#34;\u0026gt;Delete\u0026lt;/button\u0026gt; \u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/template\u0026gt; Declarative Syntax \u0026lt;script setup\u0026gt; import { View, TextInput, List, ListItem, Button } from \u0026#39;vue-declarative\u0026#39; const newTodo = ref(\u0026#39;\u0026#39;) const todos = ref([]) function addTodo() { todos.value.push({ id: Date.now(), text: newTodo.value }) newTodo.value = \u0026#39;\u0026#39; } function removeTodo(id) { todos.value = todos.value.filter(t =\u0026gt; t.id !== id) } \u0026lt;/script\u0026gt; \u0026lt;template\u0026gt; \u0026lt;View class=\u0026#34;todo-app\u0026#34;\u0026gt; \u0026lt;TextInput v-model={newTodo} onSubmit={addTodo} placeholder=\u0026#34;Add a todo\u0026#34; /\u0026gt; \u0026lt;List\u0026gt; \u0026lt;ListItem v-for=\u0026#34;todo in todos\u0026#34; :key=\u0026#34;todo.id\u0026#34; \u0026gt; \u0026lt;Text\u0026gt;{todo.text}\u0026lt;/Text\u0026gt; \u0026lt;Button onPress={() =\u0026gt; removeTodo(todo.id)}\u0026gt; Delete \u0026lt;/Button\u0026gt; \u0026lt;/ListItem\u0026gt; \u0026lt;/List\u0026gt; \u0026lt;/View\u0026gt; \u0026lt;/template\u0026gt; Performance Considerations The declarative syntax can offer performance benefits:\nBetter tree-shaking: Unused components are easier to eliminate Optimized rendering: More predictable component updates Smaller bundle size: More efficient code generation When to Use Consider the declarative syntax when:\nBuilding new projects Targeting mobile platforms Needing better TypeScript support Working with design systems Building component libraries Stick with traditional templates when:\nMaintaining legacy codebases Team is more familiar with HTML Working with existing Vue 2 projects Conclusion Vue\u0026rsquo;s new declarative UI syntax represents an evolution towards more modern, type-safe, and mobile-friendly development patterns. While it\u0026rsquo;s not a replacement for traditional templates, it offers developers more options and brings Vue closer to the patterns used in native mobile development.\nThis change makes Vue more versatile and positions it well for cross-platform development scenarios.\n","permalink":"https://pixcave.com/posts/vue-declarative-ui-syntax/","summary":"\u003cp\u003eVue is introducing support for declarative UI syntax, bringing it closer to mobile development patterns seen in Kotlin and Swift. This new approach moves away from traditional HTML templates, offering a more modern, type-safe way to build user interfaces.\u003c/p\u003e\n\u003ch2 id=\"the-evolution\"\u003eThe Evolution\u003c/h2\u003e\n\u003cp\u003eTraditional Vue templates use HTML:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-vue\" data-lang=\"vue\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;container\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eh1\u003c/span\u003e\u0026gt;{{ \u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e }}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eh1\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebutton\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e@click\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e=\u0026#34;handleClick\u0026#34;\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eClick\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eme\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebutton\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe new declarative syntax is more similar to SwiftUI or Jetpack Compose:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-vue\" data-lang=\"vue\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetup\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eView\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eText\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eButton\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;vue-declarative\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello World\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleClick\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Clicked!\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003eView\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;container\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eText\u003c/span\u003e\u0026gt;{{ \u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e }}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eText\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eButton\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonPress\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;{handleClick}\u0026#34;\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eClick\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eme\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eButton\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eView\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003etemplate\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"key-benefits\"\u003eKey Benefits\u003c/h2\u003e\n\u003ch3 id=\"1-type-safety\"\u003e1. Type Safety\u003c/h3\u003e\n\u003cp\u003eThe declarative syntax provides better TypeScript support:\u003c/p\u003e","title":"Vue's New Declarative UI Syntax: Moving Towards Mobile Development Patterns"},{"content":"A critical security vulnerability has been discovered in React\u0026rsquo;s Server-Side Rendering (SSR) Server Action protocol that could lead to Remote Code Execution (RCE) on the server.\nThe Vulnerability The issue lies in how React handles Server Actions in SSR environments. When improperly configured, the Server Action protocol can allow attackers to execute arbitrary code on the server.\nHow It Works Server Actions in React allow you to call server-side functions directly from client components:\n// Server Action async function deletePost(id) { \u0026#39;use server\u0026#39;; await db.posts.delete(id); } // Client Component function Post({ post }) { return ( \u0026lt;form action={deletePost}\u0026gt; \u0026lt;input type=\u0026#34;hidden\u0026#34; name=\u0026#34;id\u0026#34; value={post.id} /\u0026gt; \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;Delete\u0026lt;/button\u0026gt; \u0026lt;/form\u0026gt; ); } The vulnerability occurs when:\nServer Actions are not properly validated Input sanitization is missing Authentication/authorization checks are bypassed The action handler executes user-controlled input Attack Scenario An attacker could craft a malicious request:\n// Malicious payload fetch(\u0026#39;/api/actions\u0026#39;, { method: \u0026#39;POST\u0026#39;, headers: { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39; }, body: JSON.stringify({ action: \u0026#39;eval\u0026#39;, code: \u0026#39;require(\u0026#34;child_process\u0026#34;).exec(\u0026#34;rm -rf /\u0026#34;)\u0026#39; }) }); If the server action handler doesn\u0026rsquo;t properly validate and sanitize input, this could execute arbitrary code.\nMitigation Strategies 1. Input Validation Always validate and sanitize inputs:\nasync function deletePost(formData) { \u0026#39;use server\u0026#39;; // Validate input const id = formData.get(\u0026#39;id\u0026#39;); if (!id || typeof id !== \u0026#39;string\u0026#39;) { throw new Error(\u0026#39;Invalid post ID\u0026#39;); } // Sanitize const sanitizedId = id.replace(/[^a-zA-Z0-9-]/g, \u0026#39;\u0026#39;); // Additional validation if (!isValidUUID(sanitizedId)) { throw new Error(\u0026#39;Invalid post ID format\u0026#39;); } // Proceed with safe operation await db.posts.delete(sanitizedId); } 2. Authentication \u0026amp; Authorization Always check permissions:\nasync function deletePost(formData) { \u0026#39;use server\u0026#39;; // Check authentication const session = await getSession(); if (!session?.user) { throw new Error(\u0026#39;Unauthorized\u0026#39;); } const id = formData.get(\u0026#39;id\u0026#39;); // Check authorization const post = await db.posts.findById(id); if (post.userId !== session.user.id) { throw new Error(\u0026#39;Forbidden\u0026#39;); } await db.posts.delete(id); } 3. Use Type-Safe Actions Leverage TypeScript and validation libraries:\nimport { z } from \u0026#39;zod\u0026#39;; const deletePostSchema = z.object({ id: z.string().uuid() }); async function deletePost(formData: FormData) { \u0026#39;use server\u0026#39;; const result = deletePostSchema.safeParse({ id: formData.get(\u0026#39;id\u0026#39;) }); if (!result.success) { throw new Error(\u0026#39;Invalid input\u0026#39;); } // result.data is now type-safe await db.posts.delete(result.data.id); } 4. Rate Limiting Implement rate limiting to prevent abuse:\nimport rateLimit from \u0026#39;express-rate-limit\u0026#39;; const actionLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per windowMs }); app.use(\u0026#39;/api/actions\u0026#39;, actionLimiter); 5. Content Security Policy Use CSP headers to prevent XSS attacks:\napp.use((req, res, next) =\u0026gt; { res.setHeader( \u0026#39;Content-Security-Policy\u0026#39;, \u0026#34;default-src \u0026#39;self\u0026#39;; script-src \u0026#39;self\u0026#39; \u0026#39;unsafe-inline\u0026#39;;\u0026#34; ); next(); }); Best Practices Never trust client input: Always validate and sanitize Use principle of least privilege: Actions should only do what\u0026rsquo;s necessary Implement proper logging: Log all actions for audit trails Regular security audits: Review your Server Actions regularly Keep dependencies updated: Stay current with React and security patches React\u0026rsquo;s Response The React team has acknowledged this issue and recommends:\nAlways validate Server Action inputs Use TypeScript for type safety Implement proper authentication/authorization Follow security best practices for server-side code Conclusion This vulnerability highlights the importance of:\nProper input validation Security-first development practices Regular security audits Staying informed about security updates Always treat Server Actions with the same security considerations as any API endpoint. The convenience of Server Actions doesn\u0026rsquo;t mean you can skip security measures.\nStay secure, stay updated!\n","permalink":"https://pixcave.com/posts/react-ssr-security-vulnerability/","summary":"\u003cp\u003eA critical security vulnerability has been discovered in React\u0026rsquo;s Server-Side Rendering (SSR) Server Action protocol that could lead to \u003cstrong\u003eRemote Code Execution (RCE)\u003c/strong\u003e on the server.\u003c/p\u003e\n\u003ch2 id=\"the-vulnerability\"\u003eThe Vulnerability\u003c/h2\u003e\n\u003cp\u003eThe issue lies in how React handles Server Actions in SSR environments. When improperly configured, the Server Action protocol can allow attackers to execute arbitrary code on the server.\u003c/p\u003e\n\u003ch2 id=\"how-it-works\"\u003eHow It Works\u003c/h2\u003e\n\u003cp\u003eServer Actions in React allow you to call server-side functions directly from client components:\u003c/p\u003e","title":"React SSR Server Action Protocol: Critical Security Vulnerability"},{"content":"Don\u0026rsquo;t just be a tool user! Let\u0026rsquo;s build a frontend error monitoring SDK from scratch. This hands-on guide will walk you through creating your own error tracking system.\nWhy Build Your Own SDK? While there are excellent error monitoring services like Sentry, Rollbar, and Bugsnag, building your own SDK helps you:\nUnderstand how error monitoring works under the hood Customize error tracking to your specific needs Learn valuable debugging and monitoring concepts Reduce dependency on third-party services Core Features Our SDK will include:\nError Capture: Catch JavaScript errors, unhandled promise rejections Error Reporting: Send errors to a backend service User Context: Capture user information and session data Performance Monitoring: Track page load times and performance metrics Source Maps: Support for source map debugging Implementation 1. Basic Error Capture class ErrorMonitor { constructor(options = {}) { this.apiUrl = options.apiUrl || \u0026#39;/api/errors\u0026#39;; this.environment = options.environment || \u0026#39;production\u0026#39;; this.init(); } init() { // Capture unhandled errors window.addEventListener(\u0026#39;error\u0026#39;, (event) =\u0026gt; { this.captureError({ message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, stack: event.error?.stack, type: \u0026#39;javascript\u0026#39; }); }); // Capture unhandled promise rejections window.addEventListener(\u0026#39;unhandledrejection\u0026#39;, (event) =\u0026gt; { this.captureError({ message: event.reason?.message || \u0026#39;Unhandled Promise Rejection\u0026#39;, stack: event.reason?.stack, type: \u0026#39;promise\u0026#39; }); }); } captureError(errorData) { const errorReport = { ...errorData, timestamp: new Date().toISOString(), url: window.location.href, userAgent: navigator.userAgent, environment: this.environment, userId: this.getUserId(), sessionId: this.getSessionId() }; this.sendError(errorReport); } sendError(errorReport) { // Use sendBeacon for reliable delivery if (navigator.sendBeacon) { navigator.sendBeacon( this.apiUrl, JSON.stringify(errorReport) ); } else { // Fallback to fetch fetch(this.apiUrl, { method: \u0026#39;POST\u0026#39;, headers: { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39; }, body: JSON.stringify(errorReport), keepalive: true }).catch(console.error); } } getUserId() { // Get from localStorage, cookie, or context return localStorage.getItem(\u0026#39;userId\u0026#39;) || \u0026#39;anonymous\u0026#39;; } getSessionId() { let sessionId = sessionStorage.getItem(\u0026#39;sessionId\u0026#39;); if (!sessionId) { sessionId = this.generateId(); sessionStorage.setItem(\u0026#39;sessionId\u0026#39;, sessionId); } return sessionId; } generateId() { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } } 2. Enhanced Error Context class ErrorMonitor { // ... previous code ... captureError(errorData) { const errorReport = { ...errorData, timestamp: new Date().toISOString(), url: window.location.href, userAgent: navigator.userAgent, environment: this.environment, userId: this.getUserId(), sessionId: this.getSessionId(), // Additional context viewport: { width: window.innerWidth, height: window.innerHeight }, performance: this.getPerformanceMetrics(), breadcrumbs: this.getBreadcrumbs(), customData: this.customData }; this.sendError(errorReport); } getPerformanceMetrics() { if (!window.performance) return null; const timing = window.performance.timing; return { dns: timing.domainLookupEnd - timing.domainLookupStart, tcp: timing.connectEnd - timing.connectStart, request: timing.responseStart - timing.requestStart, response: timing.responseEnd - timing.responseStart, dom: timing.domContentLoadedEventEnd - timing.domLoading, load: timing.loadEventEnd - timing.navigationStart }; } addBreadcrumb(category, message, data) { if (!this.breadcrumbs) { this.breadcrumbs = []; } this.breadcrumbs.push({ category, message, data, timestamp: Date.now() }); // Keep only last 50 breadcrumbs if (this.breadcrumbs.length \u0026gt; 50) { this.breadcrumbs.shift(); } } getBreadcrumbs() { return this.breadcrumbs || []; } } 3. Usage // Initialize const monitor = new ErrorMonitor({ apiUrl: \u0026#39;https://your-api.com/errors\u0026#39;, environment: \u0026#39;production\u0026#39; }); // Add custom breadcrumbs monitor.addBreadcrumb(\u0026#39;user\u0026#39;, \u0026#39;User clicked button\u0026#39;, { buttonId: \u0026#39;submit\u0026#39; }); // Manually capture errors try { // your code } catch (error) { monitor.captureError({ message: error.message, stack: error.stack, type: \u0026#39;manual\u0026#39; }); } Advanced Features Source Map Support To support source maps, you\u0026rsquo;ll need to:\nUpload source maps to your server Parse stack traces and map them back to original sources Display original file names and line numbers in your error dashboard Error Grouping Implement error grouping to avoid duplicate reports:\ngenerateErrorFingerprint(error) { // Create a unique fingerprint based on error characteristics const key = `${error.message}-${error.filename}-${error.lineno}`; return btoa(key).substring(0, 16); } Rate Limiting Prevent overwhelming your server:\nclass ErrorMonitor { constructor(options = {}) { this.maxErrorsPerMinute = options.maxErrorsPerMinute || 10; this.errorCount = 0; this.errorWindow = Date.now(); // ... } shouldSendError() { const now = Date.now(); if (now - this.errorWindow \u0026gt; 60000) { this.errorCount = 0; this.errorWindow = now; } return this.errorCount \u0026lt; this.maxErrorsPerMinute; } captureError(errorData) { if (!this.shouldSendError()) { console.warn(\u0026#39;Error rate limit exceeded\u0026#39;); return; } this.errorCount++; // ... rest of capture logic } } Conclusion Building your own error monitoring SDK is a great learning experience. While production systems may require more features (like error aggregation, alerting, and dashboards), this foundation gives you the core concepts needed to understand how error monitoring works.\nStart simple, iterate, and add features as needed!\n","permalink":"https://pixcave.com/posts/building-frontend-error-monitoring-sdk/","summary":"\u003cp\u003eDon\u0026rsquo;t just be a tool user! Let\u0026rsquo;s build a frontend error monitoring SDK from scratch. This hands-on guide will walk you through creating your own error tracking system.\u003c/p\u003e\n\u003ch2 id=\"why-build-your-own-sdk\"\u003eWhy Build Your Own SDK?\u003c/h2\u003e\n\u003cp\u003eWhile there are excellent error monitoring services like Sentry, Rollbar, and Bugsnag, building your own SDK helps you:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUnderstand how error monitoring works under the hood\u003c/li\u003e\n\u003cli\u003eCustomize error tracking to your specific needs\u003c/li\u003e\n\u003cli\u003eLearn valuable debugging and monitoring concepts\u003c/li\u003e\n\u003cli\u003eReduce dependency on third-party services\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"core-features\"\u003eCore Features\u003c/h2\u003e\n\u003cp\u003eOur SDK will include:\u003c/p\u003e","title":"Building a Frontend Error Monitoring SDK from Scratch"},{"content":"Debugging is an essential skill for any developer, but it can be time-consuming. Here are practical strategies that helped me cut my debugging time in half.\n1. Use Browser DevTools Effectively Master the Chrome DevTools or Firefox Developer Tools:\nBreakpoints: Set breakpoints strategically, not just on errors Network Tab: Monitor API calls and identify slow requests Performance Tab: Profile your application to find bottlenecks Console: Use console.table() for better data visualization 2. Leverage AI-Powered Debugging Tools Modern AI tools can significantly speed up debugging:\nGitHub Copilot: Get suggestions for fixing errors ChatGPT/Claude: Describe your bug and get debugging strategies Cursor AI: Real-time code analysis and suggestions 3. Write Better Error Messages When you encounter an error, improve the error message before moving on:\n// Bad if (!user) throw new Error(\u0026#34;Error\u0026#34;); // Good if (!user) { throw new Error(`User not found. Expected user object, got: ${typeof user}`); } 4. Use TypeScript TypeScript catches many errors at compile time:\ninterface User { id: string; name: string; } function getUser(id: string): User { // TypeScript will catch type mismatches } 5. Implement Comprehensive Logging Add strategic logging points:\nfunction processPayment(amount) { console.log(\u0026#39;[Payment] Starting process\u0026#39;, { amount, timestamp: Date.now() }); try { // payment logic console.log(\u0026#39;[Payment] Success\u0026#39;, { transactionId }); } catch (error) { console.error(\u0026#39;[Payment] Failed\u0026#39;, { error, amount, stack: error.stack }); throw error; } } 6. Use Debugging Libraries Libraries like debug can help:\nimport debug from \u0026#39;debug\u0026#39;; const log = debug(\u0026#39;app:payment\u0026#39;); log(\u0026#39;Processing payment\u0026#39;, { amount }); 7. Reproduce Issues Systematically When debugging:\nIsolate the problem: Remove unrelated code Create a minimal reproduction: Simplify until you find the root cause Test incrementally: Add code back piece by piece 8. Use Source Maps Ensure source maps are enabled in production for easier debugging:\n// webpack.config.js module.exports = { devtool: \u0026#39;source-map\u0026#39;, // ... }; 9. Leverage React DevTools / Vue DevTools If using React or Vue, use their respective DevTools extensions to inspect component state and props.\n10. Document Your Debugging Process Keep notes on common issues and their solutions. This creates a knowledge base for future debugging sessions.\nConclusion Effective debugging is about having the right tools, processes, and mindset. By implementing these strategies, you can significantly reduce debugging time and become a more efficient developer.\n","permalink":"https://pixcave.com/posts/frontend-debugging-guide/","summary":"\u003cp\u003eDebugging is an essential skill for any developer, but it can be time-consuming. Here are practical strategies that helped me cut my debugging time in half.\u003c/p\u003e\n\u003ch2 id=\"1-use-browser-devtools-effectively\"\u003e1. Use Browser DevTools Effectively\u003c/h2\u003e\n\u003cp\u003eMaster the Chrome DevTools or Firefox Developer Tools:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eBreakpoints\u003c/strong\u003e: Set breakpoints strategically, not just on errors\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNetwork Tab\u003c/strong\u003e: Monitor API calls and identify slow requests\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePerformance Tab\u003c/strong\u003e: Profile your application to find bottlenecks\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConsole\u003c/strong\u003e: Use \u003ccode\u003econsole.table()\u003c/code\u003e for better data visualization\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-leverage-ai-powered-debugging-tools\"\u003e2. Leverage AI-Powered Debugging Tools\u003c/h2\u003e\n\u003cp\u003eModern AI tools can significantly speed up debugging:\u003c/p\u003e","title":"How I Cut My Debugging Time in Half as a Front-End Developer"},{"content":"The question \u0026ldquo;Will WebAssembly kill JavaScript?\u0026rdquo; has been circulating in the developer community for years. Let\u0026rsquo;s explore this topic with a practical perspective.\nWhat is WebAssembly? WebAssembly (WASM) is a binary instruction format for a stack-based virtual machine. It\u0026rsquo;s designed as a portable compilation target for high-level languages like C, C++, Rust, and Go, enabling deployment on the web for client and server applications.\nJavaScript\u0026rsquo;s Strengths JavaScript has several advantages that make it unlikely to be completely replaced:\nEcosystem: JavaScript has an enormous ecosystem with millions of packages on npm Developer Experience: Modern JavaScript tooling is excellent (TypeScript, bundlers, etc.) Flexibility: JavaScript is dynamically typed and very flexible Browser Integration: Deep integration with DOM APIs Community: Massive developer community and resources WebAssembly\u0026rsquo;s Role WebAssembly isn\u0026rsquo;t designed to replace JavaScript, but rather to complement it:\nPerformance-Critical Code: WASM excels at computationally intensive tasks Language Diversity: Allows developers to use languages like Rust, C++, or Go in the browser Legacy Code: Can port existing codebases to the web Security: Sandboxed execution environment The Reality The future is likely a hybrid approach:\nJavaScript for UI logic, DOM manipulation, and general web development WebAssembly for performance-critical computations, game engines, image/video processing, and scientific computing Conclusion WebAssembly won\u0026rsquo;t kill JavaScript. Instead, they\u0026rsquo;ll coexist, with each technology being used where it makes the most sense. JavaScript will continue to dominate web development, while WebAssembly will handle the heavy computational lifting.\nThe best developers will learn both and use them together to build better web applications.\n","permalink":"https://pixcave.com/posts/webassembly-vs-javascript/","summary":"\u003cp\u003eThe question \u0026ldquo;Will WebAssembly kill JavaScript?\u0026rdquo; has been circulating in the developer community for years. Let\u0026rsquo;s explore this topic with a practical perspective.\u003c/p\u003e\n\u003ch2 id=\"what-is-webassembly\"\u003eWhat is WebAssembly?\u003c/h2\u003e\n\u003cp\u003eWebAssembly (WASM) is a binary instruction format for a stack-based virtual machine. It\u0026rsquo;s designed as a portable compilation target for high-level languages like C, C++, Rust, and Go, enabling deployment on the web for client and server applications.\u003c/p\u003e\n\u003ch2 id=\"javascripts-strengths\"\u003eJavaScript\u0026rsquo;s Strengths\u003c/h2\u003e\n\u003cp\u003eJavaScript has several advantages that make it unlikely to be completely replaced:\u003c/p\u003e","title":"Will WebAssembly Kill JavaScript? Let's Find Out"},{"content":"Django 6.0 was released today, starting another release cycle for the loved and long-lived Python web framework (now 20 years old!). It comes with a mosaic of new features, contributed to by many.\nTemplate Partials The Django Template Language now supports template partials, making it easier to encapsulate and reuse small named fragments within a template file.\nPartials are sections of a template marked by the new {% partialdef %} and {% endpartialdef %} tags. They can be reused within the same template or rendered in isolation.\nReuse partials within the same template The below template reuses a partial called filter_controls within the same template:\n\u0026lt;section id=videos\u0026gt; {% partialdef filter_controls %} \u0026lt;form\u0026gt; {{ filter_form }} \u0026lt;/form\u0026gt; {% endpartialdef %} {% partial filter_controls %} \u0026lt;ul\u0026gt; {% for video in videos %} \u0026lt;li\u0026gt; \u0026lt;h2\u0026gt;{{ video.title }}\u0026lt;/h2\u0026gt; ... \u0026lt;/li\u0026gt; {% endfor %} \u0026lt;/ul\u0026gt; {% partial filter_controls %} \u0026lt;/section\u0026gt; Tasks Framework Django now includes a built-in Tasks framework for running code outside the HTTP request–response cycle. This enables offloading work, such as sending emails or processing data, to background workers.\nDefine tasks with the new @task decorator:\nfrom django.tasks import task @task def resize_video(video_id): ... And enqueue them for background execution:\nfrom example.tasks import resize_video def upload_video(request): ... resize_video.enqueue(video.id) ... Content Security Policy Support Built-in support for the Content Security Policy (CSP) standard is now available, making it easier to protect web applications against content injection attacks such as cross-site scripting (XSS).\nTo get started, add ContentSecurityPolicyMiddleware to your MIDDLEWARE setting:\nMIDDLEWARE = [ # ... \u0026#34;django.middleware.csp.ContentSecurityPolicyMiddleware\u0026#34;, # ... ] Email API Updates Email handling in Django now uses Python\u0026rsquo;s modern email API, introduced in Python 3.6. This API, centered around the email.message.EmailMessage class, offers a cleaner and Unicode-friendly interface for composing and sending emails.\nOther Notable Changes Extended automatic shell imports: Common utilities, such as django.conf.settings, are now automatically imported to the shell by default. Dynamic field refresh on save(): GeneratedFields and fields assigned expressions are now refreshed from the database after save() on backends that support the RETURNING clause. Universal StringAgg aggregate: The new StringAgg aggregate returns the input values concatenated into a string, separated by the delimiter string. This aggregate was previously supported only for PostgreSQL. BigAutoField as the default primary key type: The DEFAULT_AUTO_FIELD setting now defaults to BigAutoField. For more details, check out the official release notes.\n","permalink":"https://pixcave.com/posts/django-6.0-whats-new/","summary":"\u003cp\u003eDjango 6.0 was released today, starting another release cycle for the loved and long-lived Python web framework (now 20 years old!). It comes with a \u003cstrong\u003emosaic\u003c/strong\u003e of new features, contributed to by many.\u003c/p\u003e\n\u003ch2 id=\"template-partials\"\u003eTemplate Partials\u003c/h2\u003e\n\u003cp\u003eThe Django Template Language now supports \u003cstrong\u003etemplate partials\u003c/strong\u003e, making it easier to encapsulate and reuse small named fragments within a template file.\u003c/p\u003e\n\u003cp\u003ePartials are sections of a template marked by the new \u003ccode\u003e{% partialdef %}\u003c/code\u003e and \u003ccode\u003e{% endpartialdef %}\u003c/code\u003e tags. They can be reused within the same template or rendered in isolation.\u003c/p\u003e","title":"Django: What's New in 6.0"},{"content":"This summary distills the DEV post “⚡ Vite vs Turbopack — The Present \u0026amp; Future of Frontend Build Tools (2025 Edition)” into key takeaways for teams choosing a tool.\nQuick comparison Dev speed: Vite is already blazing (ESM + on-demand transforms). Turbopack pushes incremental builds in Rust—slightly better for very large repos. HMR: Vite is instant/reliable; Turbopack is fast and improving. Ecosystem: Vite is framework-agnostic with a large plugin ecosystem; Turbopack is strongest in Next.js today. Prod builds: Vite uses Rollup; Turbopack still leans on Webpack for prod (transitioning). Future: Vite is experimenting with Rolldown (Rust-based Rollup successor) to close the Rust gap. How Vite works (dev vs prod) Dev: native ESM served directly; deps pre-bundled once with esbuild; code transformed on demand. Prod: Rollup bundles with tree shaking, code splitting, and minification. Turbopack highlights Rust core focused on incremental/parallel builds and heavy caching. Today powers Next.js dev mode; production migration is ongoing. When to choose which Pick Vite for framework-agnostic projects, small–medium apps, or when you want the broadest plugin ecosystem and stable DX. Watch Turbopack for large Next.js/monorepo scenarios that will benefit most from incremental builds as it matures. Tips for Vite performance Use explicit imports; avoid barrel files; warm up frequently used files; keep plugin set lean; prefer native tooling (CSS/esbuild/SWC). Bottom line: In 2025 Vite is the safe, fast default for most teams; Turbopack is promising for big Next.js codebases and will get more interesting as Rust-based production builds land.\n","permalink":"https://pixcave.com/posts/vite-vs-turbopack-2025/","summary":"\u003cp\u003eThis summary distills the DEV post “⚡ Vite vs Turbopack — The Present \u0026amp; Future of Frontend Build Tools (2025 Edition)” into key takeaways for teams choosing a tool.\u003c/p\u003e\n\u003ch2 id=\"quick-comparison\"\u003eQuick comparison\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDev speed:\u003c/strong\u003e Vite is already blazing (ESM + on-demand transforms). Turbopack pushes incremental builds in Rust—slightly better for very large repos.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHMR:\u003c/strong\u003e Vite is instant/reliable; Turbopack is fast and improving.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEcosystem:\u003c/strong\u003e Vite is framework-agnostic with a large plugin ecosystem; Turbopack is strongest in Next.js today.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProd builds:\u003c/strong\u003e Vite uses Rollup; Turbopack still leans on Webpack for prod (transitioning).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFuture:\u003c/strong\u003e Vite is experimenting with Rolldown (Rust-based Rollup successor) to close the Rust gap.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"how-vite-works-dev-vs-prod\"\u003eHow Vite works (dev vs prod)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDev: native ESM served directly; deps pre-bundled once with esbuild; code transformed on demand.\u003c/li\u003e\n\u003cli\u003eProd: Rollup bundles with tree shaking, code splitting, and minification.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"turbopack-highlights\"\u003eTurbopack highlights\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRust core focused on incremental/parallel builds and heavy caching.\u003c/li\u003e\n\u003cli\u003eToday powers Next.js dev mode; production migration is ongoing.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"when-to-choose-which\"\u003eWhen to choose which\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePick \u003cstrong\u003eVite\u003c/strong\u003e for framework-agnostic projects, small–medium apps, or when you want the broadest plugin ecosystem and stable DX.\u003c/li\u003e\n\u003cli\u003eWatch \u003cstrong\u003eTurbopack\u003c/strong\u003e for large Next.js/monorepo scenarios that will benefit most from incremental builds as it matures.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"tips-for-vite-performance\"\u003eTips for Vite performance\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse explicit imports; avoid barrel files; warm up frequently used files; keep plugin set lean; prefer native tooling (CSS/esbuild/SWC).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eBottom line:\u003c/strong\u003e In 2025 Vite is the safe, fast default for most teams; Turbopack is promising for big Next.js codebases and will get more interesting as Rust-based production builds land.\u003c/p\u003e","title":"Vite vs Turbopack: Frontend Build Tools in 2025"},{"content":"Based on the DEV article “Building Performant UI with Rust, WebAssembly, and Tailwind CSS,” this summary focuses on the architecture and steps to integrate the stack.\nWhy Rust + WASM Offload CPU-heavy tasks (parsing, transforms, image ops) from the JS main thread. Near-native speed with memory safety. Keeps UI responsive while heavy logic runs in WASM. Why Tailwind here Utility-first styling keeps CSS minimal and predictable. Co-locate styles with components; avoid global collisions. Fast to iterate on responsive layouts for WASM-powered widgets. Integration workflow Compile Rust to WASM with wasm-pack/wasm-bindgen. Import the .wasm module via your bundler (Vite/Webpack/esbuild) and expose JS bindings. Call Rust functions from JS; render results in Tailwind-styled components. Use containers like overflow-x-auto, max-w-full, sm:rounded-lg to keep WASM widgets responsive. Example flow (pseudo) // rust-lib/src/lib.rs (simplified) #[wasm_bindgen] pub fn summarize(data: String) -\u0026gt; String { // heavy work here... format!(\u0026#34;size: {}\u0026#34;, data.len()) } // web/src/useSummarize.ts import init, { summarize } from \u0026#34;rust-wasm-lib\u0026#34;; export async function useSummarize(input: string) { await init(); return summarize(input); } Performance notes Keep WASM modules small; lazy-load them when the feature is needed. Avoid blocking the main thread—invoke WASM in response to user actions, not eagerly. Profile with browser DevTools + wasm-bindgen debug symbols when needed. Design principles Establish Tailwind design tokens/utilities for spacing/typography early. Encapsulate WASM widgets as reusable components with clear props. Reserve space to prevent layout shifts when results arrive. Good fits Data/analytics dashboards, heavy transforms, visualization prep. Fintech/scientific tools where CPU work dominates. Developer tools needing deterministic, fast processing in-browser. Takeaway: Let Rust/WASM handle the heavy lifting while Tailwind keeps the UI lean and consistent—yielding responsive, performant web experiences.\n","permalink":"https://pixcave.com/posts/rust-wasm-tailwind-performant-ui/","summary":"\u003cp\u003eBased on the DEV article “Building Performant UI with Rust, WebAssembly, and Tailwind CSS,” this summary focuses on the architecture and steps to integrate the stack.\u003c/p\u003e\n\u003ch2 id=\"why-rust--wasm\"\u003eWhy Rust + WASM\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOffload CPU-heavy tasks (parsing, transforms, image ops) from the JS main thread.\u003c/li\u003e\n\u003cli\u003eNear-native speed with memory safety.\u003c/li\u003e\n\u003cli\u003eKeeps UI responsive while heavy logic runs in WASM.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"why-tailwind-here\"\u003eWhy Tailwind here\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUtility-first styling keeps CSS minimal and predictable.\u003c/li\u003e\n\u003cli\u003eCo-locate styles with components; avoid global collisions.\u003c/li\u003e\n\u003cli\u003eFast to iterate on responsive layouts for WASM-powered widgets.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"integration-workflow\"\u003eIntegration workflow\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eCompile Rust to WASM with \u003ccode\u003ewasm-pack\u003c/code\u003e/\u003ccode\u003ewasm-bindgen\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eImport the \u003ccode\u003e.wasm\u003c/code\u003e module via your bundler (Vite/Webpack/esbuild) and expose JS bindings.\u003c/li\u003e\n\u003cli\u003eCall Rust functions from JS; render results in Tailwind-styled components.\u003c/li\u003e\n\u003cli\u003eUse containers like \u003ccode\u003eoverflow-x-auto\u003c/code\u003e, \u003ccode\u003emax-w-full\u003c/code\u003e, \u003ccode\u003esm:rounded-lg\u003c/code\u003e to keep WASM widgets responsive.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"example-flow-pseudo\"\u003eExample flow (pseudo)\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ts\" data-lang=\"ts\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// rust-lib/src/lib.rs (simplified)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e#\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ewasm_bindgen\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003epub\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esummarize\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eString\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e String {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// heavy work here...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#a6e22e\"\u003eformat\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;size: {}\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elen\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// web/src/useSummarize.ts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003esummarize\u003c/span\u003e } \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rust-wasm-lib\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseSummarize\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esummarize\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einput\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"performance-notes\"\u003ePerformance notes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep WASM modules small; lazy-load them when the feature is needed.\u003c/li\u003e\n\u003cli\u003eAvoid blocking the main thread—invoke WASM in response to user actions, not eagerly.\u003c/li\u003e\n\u003cli\u003eProfile with browser DevTools + wasm-bindgen debug symbols when needed.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"design-principles\"\u003eDesign principles\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEstablish Tailwind design tokens/utilities for spacing/typography early.\u003c/li\u003e\n\u003cli\u003eEncapsulate WASM widgets as reusable components with clear props.\u003c/li\u003e\n\u003cli\u003eReserve space to prevent layout shifts when results arrive.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"good-fits\"\u003eGood fits\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eData/analytics dashboards, heavy transforms, visualization prep.\u003c/li\u003e\n\u003cli\u003eFintech/scientific tools where CPU work dominates.\u003c/li\u003e\n\u003cli\u003eDeveloper tools needing deterministic, fast processing in-browser.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTakeaway:\u003c/strong\u003e Let Rust/WASM handle the heavy lifting while Tailwind keeps the UI lean and consistent—yielding responsive, performant web experiences.\u003c/p\u003e","title":"Rust + WebAssembly + Tailwind: Building Fast, Styled UIs"},{"content":"Client defaults Set Timeout on http.Client; set Transport with DialContext timeout (e.g., 3s), TLSHandshakeTimeout (3s), ResponseHeaderTimeout (5s), IdleConnTimeout (90s), MaxIdleConns/MaxIdleConnsPerHost. Retry only idempotent methods with backoff + jitter; cap attempts. Use context.WithTimeout per request; cancel on exit. Server defaults ReadHeaderTimeout (e.g., 5s) to mitigate slowloris. ReadTimeout/WriteTimeout to bound handler time (align with business SLAs). IdleTimeout to recycle idle connections; prefer HTTP/2 when available. Patterns Wrap handlers with middleware for deadline + logging when timeouts hit. For upstreams, expose metrics: connect latency, TLS handshake, TTFB, retries. Prefer connection re-use; avoid per-request clients. Checklist Timeouts set on both client and server. Retries limited to idempotent verbs with jitter. Connection pooling tuned; idle conns reused. Metrics for latency stages and timeouts. ","permalink":"https://pixcave.com/posts/go-http-timeouts-resilience/","summary":"\u003ch2 id=\"client-defaults\"\u003eClient defaults\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet \u003ccode\u003eTimeout\u003c/code\u003e on \u003ccode\u003ehttp.Client\u003c/code\u003e; set \u003ccode\u003eTransport\u003c/code\u003e with \u003ccode\u003eDialContext\u003c/code\u003e timeout (e.g., 3s), \u003ccode\u003eTLSHandshakeTimeout\u003c/code\u003e (3s), \u003ccode\u003eResponseHeaderTimeout\u003c/code\u003e (5s), \u003ccode\u003eIdleConnTimeout\u003c/code\u003e (90s), \u003ccode\u003eMaxIdleConns\u003c/code\u003e/\u003ccode\u003eMaxIdleConnsPerHost\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eRetry only idempotent methods with backoff + jitter; cap attempts.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003econtext.WithTimeout\u003c/code\u003e per request; cancel on exit.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"server-defaults\"\u003eServer defaults\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eReadHeaderTimeout\u003c/code\u003e (e.g., 5s) to mitigate slowloris.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eReadTimeout\u003c/code\u003e/\u003ccode\u003eWriteTimeout\u003c/code\u003e to bound handler time (align with business SLAs).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eIdleTimeout\u003c/code\u003e to recycle idle connections; prefer HTTP/2 when available.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"patterns\"\u003ePatterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWrap handlers with middleware for deadline + logging when timeouts hit.\u003c/li\u003e\n\u003cli\u003eFor upstreams, expose metrics: connect latency, TLS handshake, TTFB, retries.\u003c/li\u003e\n\u003cli\u003ePrefer connection re-use; avoid per-request clients.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Timeouts set on both client and server.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Retries limited to idempotent verbs with jitter.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Connection pooling tuned; idle conns reused.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics for latency stages and timeouts.\u003c/li\u003e\n\u003c/ul\u003e","title":"Go HTTP Timeouts \u0026 Resilience Defaults"},{"content":"Test design Define goals: latency budgets (p95/p99), error ceilings, throughput targets. Scenarios: ramping arrival rate, soak tests, spike tests; match production payloads. Include auth headers and realistic think time. k6 script skeleton import http from \u0026#34;k6/http\u0026#34;; import { check, sleep } from \u0026#34;k6\u0026#34;; export const options = { thresholds: { http_req_duration: [\u0026#34;p(95)\u0026lt;300\u0026#34;] }, scenarios: { api: { executor: \u0026#34;ramping-arrival-rate\u0026#34;, startRate: 10, timeUnit: \u0026#34;1s\u0026#34;, preAllocatedVUs: 50, maxVUs: 200, stages: [ { target: 100, duration: \u0026#34;3m\u0026#34; }, { target: 100, duration: \u0026#34;10m\u0026#34; }, { target: 0, duration: \u0026#34;2m\u0026#34; }, ]}, }, }; export default function () { const res = http.get(\u0026#34;https://api.example.com/resource\u0026#34;); check(res, { \u0026#34;status 200\u0026#34;: (r) =\u0026gt; r.status === 200 }); sleep(1); } Run \u0026amp; observe Capture k6 summary + JSON output; feed to Grafana for trends. Correlate with Go metrics (pprof, Prometheus) to find CPU/alloc hot paths. Record build SHA; compare runs release over release. Checklist Scenarios match prod traffic shape. Thresholds tied to SLOs; tests fail on regressions. Service metrics/pprof captured during runs. ","permalink":"https://pixcave.com/posts/go-rest-api-benchmarking-k6/","summary":"\u003ch2 id=\"test-design\"\u003eTest design\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDefine goals: latency budgets (p95/p99), error ceilings, throughput targets.\u003c/li\u003e\n\u003cli\u003eScenarios: ramping arrival rate, soak tests, spike tests; match production payloads.\u003c/li\u003e\n\u003cli\u003eInclude auth headers and realistic think time.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"k6-script-skeleton\"\u003ek6 script skeleton\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehttp\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;k6/http\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003echeck\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;k6\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoptions\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ethresholds\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ehttp_req_duration\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;p(95)\u0026lt;300\u0026#34;\u003c/span\u003e] },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003escenarios\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eapi\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eexecutor\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ramping-arrival-rate\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003estartRate\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003etimeUnit\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1s\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003epreAllocatedVUs\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003emaxVUs\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003estages\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      { \u003cspan style=\"color:#a6e22e\"\u003etarget\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eduration\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;3m\u0026#34;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      { \u003cspan style=\"color:#a6e22e\"\u003etarget\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eduration\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10m\u0026#34;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      { \u003cspan style=\"color:#a6e22e\"\u003etarget\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eduration\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;2m\u0026#34;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehttp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://api.example.com/resource\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echeck\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e, { \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;status 200\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003er\u003c/span\u003e) =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003er\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"run--observe\"\u003eRun \u0026amp; observe\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCapture k6 summary + JSON output; feed to Grafana for trends.\u003c/li\u003e\n\u003cli\u003eCorrelate with Go metrics (pprof, Prometheus) to find CPU/alloc hot paths.\u003c/li\u003e\n\u003cli\u003eRecord build SHA; compare runs release over release.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Scenarios match prod traffic shape.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Thresholds tied to SLOs; tests fail on regressions.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Service metrics/pprof captured during runs.\u003c/li\u003e\n\u003c/ul\u003e","title":"Benchmarking Go REST APIs with k6"},{"content":"When to use CPU-bound tasks (crypto, compression, image/video processing) that would block event loop. Avoid for short, tiny tasks—overhead may outweigh benefit. Patterns Use a pool (e.g., piscina/workerpool) with bounded size; queue tasks. Pass data via Transferable when large buffers; avoid heavy serialization. Propagate cancellation/timeouts; surface errors to main thread. Observability Track queue length, task duration, worker utilization, crashes. Monitor event loop lag to confirm offload benefits. Safety Validate inputs in main thread; avoid untrusted code in workers. Cleanly shut down pool on SIGTERM; drain and close workers. Checklist CPU tasks isolated to workers; pool sized to cores. Transferables used for big buffers; timeouts set. Metrics for queue/utilization/errors in place. ","permalink":"https://pixcave.com/posts/node-worker-threads-cpu-tasks/","summary":"\u003ch2 id=\"when-to-use\"\u003eWhen to use\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCPU-bound tasks (crypto, compression, image/video processing) that would block event loop.\u003c/li\u003e\n\u003cli\u003eAvoid for short, tiny tasks—overhead may outweigh benefit.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"patterns\"\u003ePatterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse a pool (e.g., piscina/workerpool) with bounded size; queue tasks.\u003c/li\u003e\n\u003cli\u003ePass data via \u003ccode\u003eTransferable\u003c/code\u003e when large buffers; avoid heavy serialization.\u003c/li\u003e\n\u003cli\u003ePropagate cancellation/timeouts; surface errors to main thread.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eTrack queue length, task duration, worker utilization, crashes.\u003c/li\u003e\n\u003cli\u003eMonitor event loop lag to confirm offload benefits.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"safety\"\u003eSafety\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eValidate inputs in main thread; avoid untrusted code in workers.\u003c/li\u003e\n\u003cli\u003eCleanly shut down pool on SIGTERM; drain and close workers.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e CPU tasks isolated to workers; pool sized to cores.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Transferables used for big buffers; timeouts set.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics for queue/utilization/errors in place.\u003c/li\u003e\n\u003c/ul\u003e","title":"Node.js Worker Threads for CPU Tasks"},{"content":"Producers acks=all, min.insync.replicas\u0026gt;=2, idempotent producer on; enable transactions for exactly-once pipelines. Tune batch.size/linger.ms for throughput; cap max.in.flight.requests.per.connection for ordering. Handle retries with backoff; surface delivery errors. Consumers enable.auto.commit=false; commit after processing; DLT for poison messages. Size max.poll.interval.ms to work time; bound max.poll.records. Isolate heavy work in worker pool; keep poll loop fast. Topics \u0026amp; brokers RF ≥ 3; clean-up policy fit (delete vs compact); segment/retention sized to storage. Monitor ISR, under-replicated partitions, controller changes, request latency, disk usage. Throttle large produce/fetch; use quotas per client if needed. Checklist Producers idempotent, acks=all, MISR set. Consumers manual commit + DLT. RF/retention sized; ISR/URP monitored. Alerts on broker latency/disk/replication health. ","permalink":"https://pixcave.com/posts/mq-kafka-reliability-playbook/","summary":"\u003ch2 id=\"producers\"\u003eProducers\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eacks=all\u003c/code\u003e, \u003ccode\u003emin.insync.replicas\u0026gt;=2\u003c/code\u003e, idempotent producer on; enable transactions for exactly-once pipelines.\u003c/li\u003e\n\u003cli\u003eTune batch.size/linger.ms for throughput; cap \u003ccode\u003emax.in.flight.requests.per.connection\u003c/code\u003e for ordering.\u003c/li\u003e\n\u003cli\u003eHandle retries with backoff; surface delivery errors.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"consumers\"\u003eConsumers\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eenable.auto.commit=false\u003c/code\u003e; commit after processing; DLT for poison messages.\u003c/li\u003e\n\u003cli\u003eSize \u003ccode\u003emax.poll.interval.ms\u003c/code\u003e to work time; bound \u003ccode\u003emax.poll.records\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eIsolate heavy work in worker pool; keep poll loop fast.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"topics--brokers\"\u003eTopics \u0026amp; brokers\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRF ≥ 3; clean-up policy fit (delete vs compact); segment/retention sized to storage.\u003c/li\u003e\n\u003cli\u003eMonitor ISR, under-replicated partitions, controller changes, request latency, disk usage.\u003c/li\u003e\n\u003cli\u003eThrottle large produce/fetch; use quotas per client if needed.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Producers idempotent, acks=all, MISR set.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Consumers manual commit + DLT.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e RF/retention sized; ISR/URP monitored.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Alerts on broker latency/disk/replication health.\u003c/li\u003e\n\u003c/ul\u003e","title":"Kafka Reliability Playbook"},{"content":"Performance notes Fastify: schema-driven, AJV validation, low-overhead routing; typically better RPS and lower p99s. Express: mature ecosystem; middleware can add overhead; great for quick prototypes. Bench considerations Compare with same validation/parsing; disable unnecessary middleware in Express. Test under keep-alive and HTTP/1.1 \u0026amp; HTTP/2 where applicable. Measure event loop lag and heap; not just RPS. Migration tips Start new services with Fastify; for existing Express apps, migrate edge routes first. Replace middleware with hooks/plugins; map Express middlewares to Fastify equivalents. Validate payloads with JSON schema for speed and safety. Operational tips Use pino (Fastify default) for structured logs; avoid console log overhead. Keep plugin count minimal; watch async hooks cost. Load test with realistic payload sizes; profile hotspots before/after migration. Takeaway: Fastify wins on raw throughput and structured DX; Express still fine for smaller apps, but performance-critical services benefit from Fastify’s lower overhead.\n","permalink":"https://pixcave.com/posts/node-scaling-fastify-vs-express/","summary":"\u003ch2 id=\"performance-notes\"\u003ePerformance notes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFastify: schema-driven, AJV validation, low-overhead routing; typically better RPS and lower p99s.\u003c/li\u003e\n\u003cli\u003eExpress: mature ecosystem; middleware can add overhead; great for quick prototypes.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"bench-considerations\"\u003eBench considerations\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCompare with same validation/parsing; disable unnecessary middleware in Express.\u003c/li\u003e\n\u003cli\u003eTest under keep-alive and HTTP/1.1 \u0026amp; HTTP/2 where applicable.\u003c/li\u003e\n\u003cli\u003eMeasure event loop lag and heap; not just RPS.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"migration-tips\"\u003eMigration tips\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eStart new services with Fastify; for existing Express apps, migrate edge routes first.\u003c/li\u003e\n\u003cli\u003eReplace middleware with hooks/plugins; map Express middlewares to Fastify equivalents.\u003c/li\u003e\n\u003cli\u003eValidate payloads with JSON schema for speed and safety.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"operational-tips\"\u003eOperational tips\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse \u003ccode\u003epino\u003c/code\u003e (Fastify default) for structured logs; avoid console log overhead.\u003c/li\u003e\n\u003cli\u003eKeep plugin count minimal; watch async hooks cost.\u003c/li\u003e\n\u003cli\u003eLoad test with realistic payload sizes; profile hotspots before/after migration.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTakeaway:\u003c/strong\u003e Fastify wins on raw throughput and structured DX; Express still fine for smaller apps, but performance-critical services benefit from Fastify’s lower overhead.\u003c/p\u003e","title":"Scaling Node.js: Fastify vs Express"},{"content":"Approaches Token bucket for burst+steady control; sliding window for fairness. Enforce at edge (gateway/ingress) plus app-level for per-tenant safety. Spring implementation Use filters/interceptors with Redis/Lua for atomic buckets. Key by tenant/user/IP; return 429 with Retry-After. Expose metrics per key and rule; alert on near-capacity. Considerations Separate auth failures from rate limits; avoid blocking login endpoints too aggressively. Keep rule configs dynamic; hot-reload from config store. Combine with circuit breakers/timeouts for upstream dependencies. Checklist Edge and app-level limits defined. Redis-based atomic counters/buckets with TTL. Metrics + logs for limit decisions; alerts in place. ","permalink":"https://pixcave.com/posts/java-rest-api-rate-limiting/","summary":"\u003ch2 id=\"approaches\"\u003eApproaches\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eToken bucket for burst+steady control; sliding window for fairness.\u003c/li\u003e\n\u003cli\u003eEnforce at edge (gateway/ingress) plus app-level for per-tenant safety.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"spring-implementation\"\u003eSpring implementation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse filters/interceptors with Redis/Lua for atomic buckets.\u003c/li\u003e\n\u003cli\u003eKey by tenant/user/IP; return \u003ccode\u003e429\u003c/code\u003e with \u003ccode\u003eRetry-After\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eExpose metrics per key and rule; alert on near-capacity.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"considerations\"\u003eConsiderations\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSeparate auth failures from rate limits; avoid blocking login endpoints too aggressively.\u003c/li\u003e\n\u003cli\u003eKeep rule configs dynamic; hot-reload from config store.\u003c/li\u003e\n\u003cli\u003eCombine with circuit breakers/timeouts for upstream dependencies.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Edge and app-level limits defined.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Redis-based atomic counters/buckets with TTL.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics + logs for limit decisions; alerts in place.\u003c/li\u003e\n\u003c/ul\u003e","title":"Rate Limiting Java REST APIs"},{"content":"Principles Keep goroutine count bounded; size pools to CPU/core and downstream QPS. Apply backpressure: bounded channels + select with default to shed load early. Context everywhere: cancel on timeouts/parent cancellation; close resources. Prefer immutability; minimize shared state. Use channels for coordination. Patterns Worker pool with buffered jobs; fan-out/fan-in via contexts. Rate limit with time.Ticker or golang.org/x/time/rate. Semaphore via buffered channel for limited resources (DB, disk, external API). Sync cheatsheet sync.Mutex for critical sections; avoid long hold times. sync.WaitGroup for bounded concurrent tasks; errgroup for cancellation on first error. sync.Map only for high-concurrency, write-light cases; prefer map+mutex otherwise. Instrument \u0026amp; guard pprof: net/http/pprof + CPU/mem profiles in staging under load. Trace blocking: GODEBUG=schedtrace=1000,scavtrace=1 when diagnosing. Metrics: goroutines, GC pause, allocations, queue depth, worker utilization. Checklist Context per request; timeouts set at ingress. Bounded goroutines; pools sized and observable. Backpressure on queues; drop/timeout strategy defined. pprof/metrics enabled in non-prod and behind auth in prod. Load tests for saturation behavior and graceful degradation. ","permalink":"https://pixcave.com/posts/go-high-performance-concurrency/","summary":"\u003ch2 id=\"principles\"\u003ePrinciples\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep goroutine count bounded; size pools to CPU/core and downstream QPS.\u003c/li\u003e\n\u003cli\u003eApply backpressure: bounded channels + select with default to shed load early.\u003c/li\u003e\n\u003cli\u003eContext everywhere: cancel on timeouts/parent cancellation; close resources.\u003c/li\u003e\n\u003cli\u003ePrefer immutability; minimize shared state. Use channels for coordination.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"patterns\"\u003ePatterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWorker pool with buffered jobs; fan-out/fan-in via contexts.\u003c/li\u003e\n\u003cli\u003eRate limit with \u003ccode\u003etime.Ticker\u003c/code\u003e or \u003ccode\u003egolang.org/x/time/rate\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSemaphore via buffered channel for limited resources (DB, disk, external API).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sync-cheatsheet\"\u003eSync cheatsheet\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003esync.Mutex\u003c/code\u003e for critical sections; avoid long hold times.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esync.WaitGroup\u003c/code\u003e for bounded concurrent tasks; \u003ccode\u003eerrgroup\u003c/code\u003e for cancellation on first error.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esync.Map\u003c/code\u003e only for high-concurrency, write-light cases; prefer map+mutex otherwise.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"instrument--guard\"\u003eInstrument \u0026amp; guard\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003epprof: \u003ccode\u003enet/http/pprof\u003c/code\u003e + CPU/mem profiles in staging under load.\u003c/li\u003e\n\u003cli\u003eTrace blocking: \u003ccode\u003eGODEBUG=schedtrace=1000,scavtrace=1\u003c/code\u003e when diagnosing.\u003c/li\u003e\n\u003cli\u003eMetrics: goroutines, GC pause, allocations, queue depth, worker utilization.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Context per request; timeouts set at ingress.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Bounded goroutines; pools sized and observable.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Backpressure on queues; drop/timeout strategy defined.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e pprof/metrics enabled in non-prod and behind auth in prod.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Load tests for saturation behavior and graceful degradation.\u003c/li\u003e\n\u003c/ul\u003e","title":"Go High-Performance Concurrency Playbook"},{"content":"Metrics Lead time, MTTR, change failure rate, deploy frequency. Stage timing (queue, build, test, deploy); flake rate; retry counts. Tracing \u0026amp; logs Trace pipeline executions with build SHA, branch, trigger source; annotate stage spans. Structured logs with status, duration, infra node; keep artifacts linked. Guardrails Quality gates (tests, lint, security scans) per PR; fail fast on criticals. Retry budget per job to avoid infinite flake loops. Rollback hooks + auto-stop on repeated failures. Ops Parallelize where safe; cache dependencies; pin tool versions. Alert on SLA breaches (queue time, total duration) and rising flake rates. Keep dashboards per repo/team; trend regressions release to release. ","permalink":"https://pixcave.com/posts/cicd-pipeline-observability/","summary":"\u003ch2 id=\"metrics\"\u003eMetrics\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLead time, MTTR, change failure rate, deploy frequency.\u003c/li\u003e\n\u003cli\u003eStage timing (queue, build, test, deploy); flake rate; retry counts.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"tracing--logs\"\u003eTracing \u0026amp; logs\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eTrace pipeline executions with build SHA, branch, trigger source; annotate stage spans.\u003c/li\u003e\n\u003cli\u003eStructured logs with status, duration, infra node; keep artifacts linked.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"guardrails\"\u003eGuardrails\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eQuality gates (tests, lint, security scans) per PR; fail fast on criticals.\u003c/li\u003e\n\u003cli\u003eRetry budget per job to avoid infinite flake loops.\u003c/li\u003e\n\u003cli\u003eRollback hooks + auto-stop on repeated failures.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ops\"\u003eOps\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eParallelize where safe; cache dependencies; pin tool versions.\u003c/li\u003e\n\u003cli\u003eAlert on SLA breaches (queue time, total duration) and rising flake rates.\u003c/li\u003e\n\u003cli\u003eKeep dashboards per repo/team; trend regressions release to release.\u003c/li\u003e\n\u003c/ul\u003e","title":"CI/CD Pipeline Observability \u0026 Guardrails"},{"content":"Workers \u0026amp; balancing Define queue priorities; dedicate workers per queue (emails, webhooks, default). Use balance strategies (simple, auto) and cap max processes per supervisor. Reliability Set retry/backoff per job; push non-idempotent tasks carefully. Configure timeout and retry_after (keep retry_after \u0026gt; max job time). Use Redis with persistence; enable horizon:supervisors monitors. Observability Horizon dashboard: throughput, runtime, failures, retries. Alert on rising failures and long runtimes; log payload/context for failed jobs. Prune failed jobs with retention policy; send to DLQ when needed. Deployment Restart Horizon on deploy to pick up code; use horizon:terminate. Ensure supervisor/systemd restarts Horizon if it dies. Checklist Queues prioritized; supervisors sized. Retries/backoff and timeouts set; DLQ plan. Monitoring/alerts configured; failed job retention in place. ","permalink":"https://pixcave.com/posts/php-laravel-horizon-queues/","summary":"\u003ch2 id=\"workers--balancing\"\u003eWorkers \u0026amp; balancing\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDefine queue priorities; dedicate workers per queue (emails, webhooks, default).\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003ebalance\u003c/code\u003e strategies (\u003ccode\u003esimple\u003c/code\u003e, \u003ccode\u003eauto\u003c/code\u003e) and cap max processes per supervisor.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"reliability\"\u003eReliability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet retry/backoff per job; push non-idempotent tasks carefully.\u003c/li\u003e\n\u003cli\u003eConfigure \u003ccode\u003etimeout\u003c/code\u003e and \u003ccode\u003eretry_after\u003c/code\u003e (keep retry_after \u0026gt; max job time).\u003c/li\u003e\n\u003cli\u003eUse Redis with persistence; enable \u003ccode\u003ehorizon:supervisors\u003c/code\u003e monitors.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHorizon dashboard: throughput, runtime, failures, retries.\u003c/li\u003e\n\u003cli\u003eAlert on rising failures and long runtimes; log payload/context for failed jobs.\u003c/li\u003e\n\u003cli\u003ePrune failed jobs with retention policy; send to DLQ when needed.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"deployment\"\u003eDeployment\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRestart Horizon on deploy to pick up code; use \u003ccode\u003ehorizon:terminate\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eEnsure supervisor/systemd restarts Horizon if it dies.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Queues prioritized; supervisors sized.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Retries/backoff and timeouts set; DLQ plan.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Monitoring/alerts configured; failed job retention in place.\u003c/li\u003e\n\u003c/ul\u003e","title":"Laravel Queues with Horizon: Reliable Setup"},{"content":"Identity \u0026amp; access Enforce strong auth (OIDC/JWT); short-lived tokens + refresh; audience/issuer checks. Fine-grained authz (RBAC/ABAC); deny-by-default; rate-limit per identity. Input \u0026amp; data Validate/normalize input; reject oversized bodies; JSON schema where possible. Output encode; avoid reflecting raw user data; paginate results. Store secrets in vault/KMS; rotate keys; never log secrets/tokens. Transport \u0026amp; headers TLS everywhere; HSTS; modern ciphers. Security headers: Content-Security-Policy, X-Content-Type-Options=nosniff, X-Frame-Options=DENY, Referrer-Policy. Abuse protection Rate limit + burst control; CAPTCHA/step-up for sensitive actions. Bot detection where relevant; geo/IP allow/deny for admin surfaces. Observability Structured audit logs with identity, action, resource, result; avoid PII spill. Alerts on auth failures, unusual rate spikes, and 5xx anomalies. Checklist AuthZ enforced; least privilege. Input validated; size limits set. TLS + security headers applied. Rate limits + abuse controls configured. Secrets vaulted and rotated. ","permalink":"https://pixcave.com/posts/security-api-hardening-checklist/","summary":"\u003ch2 id=\"identity--access\"\u003eIdentity \u0026amp; access\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEnforce strong auth (OIDC/JWT); short-lived tokens + refresh; audience/issuer checks.\u003c/li\u003e\n\u003cli\u003eFine-grained authz (RBAC/ABAC); deny-by-default; rate-limit per identity.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"input--data\"\u003eInput \u0026amp; data\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eValidate/normalize input; reject oversized bodies; JSON schema where possible.\u003c/li\u003e\n\u003cli\u003eOutput encode; avoid reflecting raw user data; paginate results.\u003c/li\u003e\n\u003cli\u003eStore secrets in vault/KMS; rotate keys; never log secrets/tokens.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"transport--headers\"\u003eTransport \u0026amp; headers\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eTLS everywhere; HSTS; modern ciphers.\u003c/li\u003e\n\u003cli\u003eSecurity headers: \u003ccode\u003eContent-Security-Policy\u003c/code\u003e, \u003ccode\u003eX-Content-Type-Options=nosniff\u003c/code\u003e, \u003ccode\u003eX-Frame-Options=DENY\u003c/code\u003e, \u003ccode\u003eReferrer-Policy\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"abuse-protection\"\u003eAbuse protection\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRate limit + burst control; CAPTCHA/step-up for sensitive actions.\u003c/li\u003e\n\u003cli\u003eBot detection where relevant; geo/IP allow/deny for admin surfaces.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eStructured audit logs with identity, action, resource, result; avoid PII spill.\u003c/li\u003e\n\u003cli\u003eAlerts on auth failures, unusual rate spikes, and 5xx anomalies.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e AuthZ enforced; least privilege.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Input validated; size limits set.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e TLS + security headers applied.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Rate limits + abuse controls configured.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Secrets vaulted and rotated.\u003c/li\u003e\n\u003c/ul\u003e","title":"API Security Hardening Checklist"},{"content":"About DevCraft Studio DevCraft Studio is a technical content platform dedicated to sharing practical software engineering knowledge gained from real-world production environments.\nOur Story DevCraft Studio began in early 2024 when a group of senior engineers realized they were solving the same problems repeatedly across different companies. We kept private notes, internal wikis, and scattered documentation – but none of it was organized or shareable.\nThe breaking point came during a production incident involving a PostgreSQL JSONB performance issue. After spending two weeks debugging, we discovered the solution buried in a 5-year-old blog post with 12 views. That\u0026rsquo;s when we decided: there had to be a better way to share these hard-won lessons.\nWe launched this site in March 2021 with just 8 articles covering our most painful debugging experiences. The response surprised us – developers facing the same issues found our content through search engines, left comments with their own solutions, and the community grew organically from there.\nToday, we publish 2-3 articles per week, covering everything from database optimization to microservices architecture. Every article is based on actual production experience, not theoretical knowledge or toy examples.\nOur Mission We believe that the best technical content comes from real battles with production systems.\nOur mission is simple:\nDocument real problems we\u0026rsquo;ve encountered in production environments Share actual solutions that worked (and explain why others didn\u0026rsquo;t) Save other developers time by publishing the debugging steps we wish we\u0026rsquo;d found Build a community where experienced engineers share war stories and lessons learned We\u0026rsquo;re not here to rehash documentation or write yet another \u0026ldquo;Getting Started with React\u0026rdquo; tutorial. There are plenty of those already. We focus on the messy, complicated, real-world problems that don\u0026rsquo;t have clean answers in the official docs.\nWhat Makes Us Different Experience over theory: Our writers are practicing engineers with 8-15 years in the industry. We write about problems we\u0026rsquo;ve actually solved, not problems we read about.\nProduction focus: Every article includes real metrics, actual code from production systems, and honest assessments of what worked and what didn\u0026rsquo;t.\nNo fluff: We skip the long introductions and get straight to the technical content. If you\u0026rsquo;re here, you already know what Redis is – we\u0026rsquo;ll tell you how to use it at scale.\nContinuous updates: Technologies change. We regularly update articles when better solutions emerge or when readers point out improvements.\nWhat You\u0026rsquo;ll Find Here Most of our content comes from solving real problems. When we run into something tricky or find a better way to do things, we write about it. You\u0026rsquo;ll see articles on:\nBackend stuff: Java, Go, Python, Node.js, PHP Frontend work: React, Vue, TypeScript System design: databases, message queues, caching DevOps: Docker, Kubernetes, deployment Things that work: patterns, practices, and lessons learned Why We Write Honestly? Writing helps us remember things. If we figured out how to fix a weird bug or optimize a slow query, documenting it means we don\u0026rsquo;t have to figure it out again next time. Plus, if it helps someone else avoid the same headache, that\u0026rsquo;s a bonus.\nGot Something to Share? Found a mistake? Have a better solution? Want to see us cover a specific topic? Want to get in touch? Just leave a comment below on any article. We read everything and try to respond when we can.\nOur Commitment to Quality Every article goes through our internal review process:\nTechnical accuracy: Code examples are tested in real environments Clarity: We rewrite until the solution is clear to someone encountering the problem for the first time Completeness: We include the context, the debugging process, and the lessons learned – not just the final solution Maintenance: We monitor comments and update articles when better approaches emerge Get Involved We\u0026rsquo;re always looking to improve:\nFound an error? Leave a comment or contact us Have a better solution? Share it in the comments – we\u0026rsquo;ll update the article and credit you Want to contribute? We occasionally accept guest posts from experienced engineers Have a topic request? Let us know what you\u0026rsquo;re struggling with Last updated: January 2026\n","permalink":"https://pixcave.com/about/","summary":"\u003ch1 id=\"about-devcraft-studio\"\u003eAbout DevCraft Studio\u003c/h1\u003e\n\u003cp\u003eDevCraft Studio is a technical content platform dedicated to sharing practical software engineering knowledge gained from real-world production environments.\u003c/p\u003e\n\u003ch2 id=\"our-story\"\u003eOur Story\u003c/h2\u003e\n\u003cp\u003eDevCraft Studio began in early 2024 when a group of senior engineers realized they were solving the same problems repeatedly across different companies. We kept private notes, internal wikis, and scattered documentation – but none of it was organized or shareable.\u003c/p\u003e\n\u003cp\u003eThe breaking point came during a production incident involving a PostgreSQL JSONB performance issue. After spending two weeks debugging, we discovered the solution buried in a 5-year-old blog post with 12 views. That\u0026rsquo;s when we decided: there had to be a better way to share these hard-won lessons.\u003c/p\u003e","title":"About"},{"content":"Contact Us We\u0026rsquo;d love to hear from you! Whether you have questions, feedback, suggestions, or just want to say hello, here\u0026rsquo;s how you can reach us.\nEmail Contact For general inquiries, feedback, or partnership opportunities:\nEmail: contact@pixcave.com\nResponse time: We typically respond within 2-3 business days.\nFor business and advertising inquiries:\nEmail: business@pixcave.com\nConnect With Us Stay updated and connect with us on social media:\nGitHub: Share your code, report issues, or contribute Twitter/X: Follow us for quick updates and tech discussions LinkedIn: Professional networking and career opportunities Report Issues Found a technical issue, broken link, or typo on our site?\nGitHub Issues: Report bugs or suggest improvements Email: tech@pixcave.com We appreciate your help in making our content better!\nFrequently Asked Questions Can I republish your articles?\nPlease see our Terms of Service for content usage guidelines. Short excerpts with attribution and a link back are welcome.\nCan I contribute an article?\nWe\u0026rsquo;re always interested in quality technical content. Email us at contact@pixcave.com with your article idea and writing samples.\nHow do I request a topic?\nLeave a comment on any article suggesting what you\u0026rsquo;d like to see covered, or email us your suggestions.\nDo you offer consulting or training?\nFor consulting inquiries, please email business@pixcave.com with details about your needs.\nAdvertising \u0026amp; Partnerships Interested in advertising, sponsorships, or collaboration opportunities?\nEmail: business@pixcave.com\nPlease include:\nType of partnership or advertising you\u0026rsquo;re interested in Your company or organization details Proposed timeline and budget range Privacy We respect your privacy. Information you provide through this contact form or email will only be used to respond to your inquiry and will not be shared with third parties without your consent. See our Privacy Policy for more details.\nBusiness Information DevCraft Studio\nTechnical Content \u0026amp; Software Development Insights\nHeadquarters: San Francisco, CA, United States\nEmail: contact@pixcave.com\nWebsite: https://pixcave.com\nWe look forward to hearing from you! While we try to respond to all inquiries, response times may vary based on volume.\nlast updated**: January 2026\n","permalink":"https://pixcave.com/contact/","summary":"\u003ch1 id=\"contact-us\"\u003eContact Us\u003c/h1\u003e\n\u003cp\u003eWe\u0026rsquo;d love to hear from you! Whether you have questions, feedback, suggestions, or just want to say hello, here\u0026rsquo;s how you can reach us.\u003c/p\u003e\n\u003ch2 id=\"email-contact\"\u003eEmail Contact\u003c/h2\u003e\n\u003cp\u003eFor general inquiries, feedback, or partnership opportunities:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eEmail\u003c/strong\u003e: \u003ca href=\"mailto:contact@pixcave.com\"\u003econtact@pixcave.com\u003c/a\u003e\u003cbr\u003e\n\u003cstrong\u003eResponse time\u003c/strong\u003e: We typically respond within 2-3 business days.\u003c/p\u003e\n\u003cp\u003eFor business and advertising inquiries:\u003cbr\u003e\n\u003cstrong\u003eEmail\u003c/strong\u003e: \u003ca href=\"mailto:business@pixcave.com\"\u003ebusiness@pixcave.com\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"connect-with-us\"\u003eConnect With Us\u003c/h2\u003e\n\u003cp\u003eStay updated and connect with us on social media:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eGitHub\u003c/strong\u003e: Share your code, report issues, or contribute\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTwitter/X\u003c/strong\u003e: Follow us for quick updates and tech discussions\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLinkedIn\u003c/strong\u003e: Professional networking and career opportunities\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"report-issues\"\u003eReport Issues\u003c/h2\u003e\n\u003cp\u003eFound a technical issue, broken link, or typo on our site?\u003c/p\u003e","title":"Contact Us"},{"content":"Privacy Policy Here\u0026rsquo;s how we handle your information when you visit this site. Short version: we collect as little as possible.\nWhat We Collect Comments When you comment, you sign in through GitHub. We don\u0026rsquo;t see or store your GitHub password. Your comments go to GitHub Discussions, and you can delete them anytime on GitHub.\nWhat shows up in comments:\nYour GitHub username Your profile picture What you wrote When you wrote it That\u0026rsquo;s it. We don\u0026rsquo;t pull any other info from your GitHub account.\nAnalytics We might look at basic stats like which pages get visited most. This helps us figure out what content people actually want. We don\u0026rsquo;t track you across other sites or build profiles.\nCookies We use cookies for one thing: remembering if you prefer dark mode or light mode. That\u0026rsquo;s stored in your browser, not on our servers. No tracking cookies, no ads.\nThird-Party Stuff Giscus Comments run through Giscus, which uses GitHub. When you comment, GitHub\u0026rsquo;s privacy policy applies. We only see what\u0026rsquo;s already public on your GitHub profile.\nHosting Our hosting provider keeps standard server logs (IPs, timestamps, etc.) for security. We don\u0026rsquo;t actively look at these unless something\u0026rsquo;s broken.\nYour Data You can:\nAsk what data we have (probably not much) Request corrections Ask us to delete stuff Opt out where possible Just contact us if you need any of this.\nHow Long We Keep Things Comments: Forever, unless you delete them on GitHub Analytics: Usually a couple years Server logs: About 90 days Kids This site isn\u0026rsquo;t for people under 13. We don\u0026rsquo;t collect info from kids.\nChanges If we update this policy, we\u0026rsquo;ll change the date at the bottom. We won\u0026rsquo;t email you about it, so check back if you\u0026rsquo;re curious.\nQuestions? Hit us up on the contact page if you want to know more.\nLast updated: January 2025\n","permalink":"https://pixcave.com/privacy-policy/","summary":"\u003ch1 id=\"privacy-policy\"\u003ePrivacy Policy\u003c/h1\u003e\n\u003cp\u003eHere\u0026rsquo;s how we handle your information when you visit this site. Short version: we collect as little as possible.\u003c/p\u003e\n\u003ch2 id=\"what-we-collect\"\u003eWhat We Collect\u003c/h2\u003e\n\u003ch3 id=\"comments\"\u003eComments\u003c/h3\u003e\n\u003cp\u003eWhen you comment, you sign in through GitHub. We don\u0026rsquo;t see or store your GitHub password. Your comments go to GitHub Discussions, and you can delete them anytime on GitHub.\u003c/p\u003e\n\u003cp\u003eWhat shows up in comments:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eYour GitHub username\u003c/li\u003e\n\u003cli\u003eYour profile picture\u003c/li\u003e\n\u003cli\u003eWhat you wrote\u003c/li\u003e\n\u003cli\u003eWhen you wrote it\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThat\u0026rsquo;s it. We don\u0026rsquo;t pull any other info from your GitHub account.\u003c/p\u003e","title":"Privacy Policy"},{"content":"Terms of Service By using this site, you\u0026rsquo;re agreeing to these terms. They\u0026rsquo;re pretty straightforward.\nUsing Our Content Feel free to:\nRead our articles Share links Use code examples in your projects (attribution is nice but not required) Code Examples All code is provided as-is. We try to make sure it works, but things break, environments differ, and mistakes happen. Always test before using in production. If something goes wrong, that\u0026rsquo;s on you, not us.\nComments When you comment:\nYou own what you write Keep it respectful and on-topic Spam and abuse get deleted We can moderate as needed By posting, you\u0026rsquo;re okay with us showing your comment here. You can delete it anytime on GitHub.\nContent Ownership Our stuff: Articles and site design belong to us. Don\u0026rsquo;t republish entire articles or claim our work as yours. Using snippets or ideas is fine.\nYour stuff: Your comments are yours. We just get to display them.\nLinks We link to other sites sometimes. We\u0026rsquo;re not responsible for what\u0026rsquo;s on those sites or how they handle your data.\nNo Warranties Everything here is \u0026ldquo;as is.\u0026rdquo; We don\u0026rsquo;t guarantee:\nThat information is 100% accurate That it\u0026rsquo;ll work for your situation That the site will always be up Liability We\u0026rsquo;re not liable for:\nProblems from using this site Data loss Downtime Mistakes in articles Use at your own risk.\nWe Can Change Things We might:\nUpdate the site Change these terms Remove content Block access We\u0026rsquo;ll try to be reasonable about it.\nLegal Stuff These terms follow applicable laws. If there\u0026rsquo;s a dispute, we\u0026rsquo;ll handle it through normal legal channels.\nQuestions? Contact us if you need clarification on anything.\nLast updated: January 2025\n","permalink":"https://pixcave.com/terms-of-service/","summary":"\u003ch1 id=\"terms-of-service\"\u003eTerms of Service\u003c/h1\u003e\n\u003cp\u003eBy using this site, you\u0026rsquo;re agreeing to these terms. They\u0026rsquo;re pretty straightforward.\u003c/p\u003e\n\u003ch2 id=\"using-our-content\"\u003eUsing Our Content\u003c/h2\u003e\n\u003cp\u003eFeel free to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRead our articles\u003c/li\u003e\n\u003cli\u003eShare links\u003c/li\u003e\n\u003cli\u003eUse code examples in your projects (attribution is nice but not required)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"code-examples\"\u003eCode Examples\u003c/h2\u003e\n\u003cp\u003eAll code is provided as-is. We try to make sure it works, but things break, environments differ, and mistakes happen. Always test before using in production. If something goes wrong, that\u0026rsquo;s on you, not us.\u003c/p\u003e","title":"Terms of Service"},{"content":"Metrics Use Micrometer + Prometheus: management.endpoints.web.exposure.include=prometheus,health,info. Add JVM+Tomcat/db pool meters; set percentiles for latencies. Create SLIs: request latency, error rate, saturation (threads/connections), GC pauses. Traces Spring Boot 3 ships with OTel starter: add spring-boot-starter-actuator + micrometer-tracing-bridge-otel + exporter (OTLP/Zipkin/Jaeger). Propagate headers (traceparent); ensure async executors use ContextPropagatingExecutor. Sample smartly: lower rates on noisy paths; raise for errors. Logs Use JSON layout; include traceId/spanId for correlation. Avoid verbose INFO in hot paths; keep payload size bounded. Dashboards \u0026amp; alerts Latency/error SLO dashboards per endpoint. DB pool saturation, thread pool queue depth, GC pause, heap used %, 5xx rate. Alerts on SLO burn rates; include exemplars linking metrics → traces → logs. Checklist Actuator endpoints secured and exposed only where needed. OTLP exporter configured; sampling tuned. Trace/log correlation verified in staging. Dashboards + alerts reviewed with oncall. ","permalink":"https://pixcave.com/posts/java-spring-boot-observability/","summary":"\u003ch2 id=\"metrics\"\u003eMetrics\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse Micrometer + Prometheus: \u003ccode\u003emanagement.endpoints.web.exposure.include=prometheus,health,info\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eAdd JVM+Tomcat/db pool meters; set percentiles for latencies.\u003c/li\u003e\n\u003cli\u003eCreate SLIs: request latency, error rate, saturation (threads/connections), GC pauses.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"traces\"\u003eTraces\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSpring Boot 3 ships with OTel starter: add \u003ccode\u003espring-boot-starter-actuator\u003c/code\u003e + \u003ccode\u003emicrometer-tracing-bridge-otel\u003c/code\u003e + exporter (OTLP/Zipkin/Jaeger).\u003c/li\u003e\n\u003cli\u003ePropagate headers (\u003ccode\u003etraceparent\u003c/code\u003e); ensure async executors use \u003ccode\u003eContextPropagatingExecutor\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSample smartly: lower rates on noisy paths; raise for errors.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"logs\"\u003eLogs\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse JSON layout; include traceId/spanId for correlation.\u003c/li\u003e\n\u003cli\u003eAvoid verbose INFO in hot paths; keep payload size bounded.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"dashboards--alerts\"\u003eDashboards \u0026amp; alerts\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLatency/error SLO dashboards per endpoint.\u003c/li\u003e\n\u003cli\u003eDB pool saturation, thread pool queue depth, GC pause, heap used %, 5xx rate.\u003c/li\u003e\n\u003cli\u003eAlerts on SLO burn rates; include exemplars linking metrics → traces → logs.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Actuator endpoints secured and exposed only where needed.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e OTLP exporter configured; sampling tuned.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Trace/log correlation verified in staging.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Dashboards + alerts reviewed with oncall.\u003c/li\u003e\n\u003c/ul\u003e","title":"Spring Boot Observability: Metrics, Traces, Logs"},{"content":"During incident Roles: incident commander, comms lead, ops/feature SMEs, scribe. Declare severity quickly; open shared channel/bridge; timestamp actions. Stabilize first: roll back, feature-flag off, scale up, or shed load. Runbooks \u0026amp; tooling Prebuilt runbooks per service: restart/rollback steps, dashboards, logs, feature flags. One-click access to dashboards (metrics, traces, logs), recent deploys, and toggles. Paging rules with escalation; avoid noisy alerts. Comms Single source of truth: incident doc; external status page if needed. Regular updates with impact, scope, mitigation, ETA. After incident Blameless postmortem; timeline, root causes, contributing factors. Action items with owners/deadlines; track to completion. Add tests/alerts/runbook updates; reduce time-to-detect and time-to-recover. ","permalink":"https://pixcave.com/posts/devops-incident-response-playbook/","summary":"\u003ch2 id=\"during-incident\"\u003eDuring incident\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRoles: incident commander, comms lead, ops/feature SMEs, scribe.\u003c/li\u003e\n\u003cli\u003eDeclare severity quickly; open shared channel/bridge; timestamp actions.\u003c/li\u003e\n\u003cli\u003eStabilize first: roll back, feature-flag off, scale up, or shed load.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"runbooks--tooling\"\u003eRunbooks \u0026amp; tooling\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrebuilt runbooks per service: restart/rollback steps, dashboards, logs, feature flags.\u003c/li\u003e\n\u003cli\u003eOne-click access to dashboards (metrics, traces, logs), recent deploys, and toggles.\u003c/li\u003e\n\u003cli\u003ePaging rules with escalation; avoid noisy alerts.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"comms\"\u003eComms\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSingle source of truth: incident doc; external status page if needed.\u003c/li\u003e\n\u003cli\u003eRegular updates with impact, scope, mitigation, ETA.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"after-incident\"\u003eAfter incident\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eBlameless postmortem; timeline, root causes, contributing factors.\u003c/li\u003e\n\u003cli\u003eAction items with owners/deadlines; track to completion.\u003c/li\u003e\n\u003cli\u003eAdd tests/alerts/runbook updates; reduce time-to-detect and time-to-recover.\u003c/li\u003e\n\u003c/ul\u003e","title":"DevOps Incident Response Playbook"},{"content":"PostgreSQL\u0026rsquo;s work_mem parameter is one of the most impactful yet misunderstood configuration settings for database performance. This post explores how adjusting work_mem can dramatically improve query execution times, especially for operations involving sorting, hashing, and joins.\nUnderstanding work_mem work_mem specifies the amount of memory PostgreSQL can use for internal sort operations and hash tables before writing to temporary disk files. The default value is 4MB, which is conservative to ensure PostgreSQL runs on smaller machines.\nWhen work_mem matters Sort operations: ORDER BY, DISTINCT, merge joins Hash operations: Hash joins, hash-based aggregation, IN subqueries Window functions: Some window function operations When data exceeds the work_mem limit, PostgreSQL switches to disk-based algorithms (external merge sort), which are significantly slower than in-memory operations.\nThe problem: disk-based sorting With insufficient work_mem, queries may show:\nSort Method: external merge Disk: 280kB This indicates the sort operation spilled to disk, causing:\nIncreased execution time Higher I/O write spikes (even for read-only queries) Reduced throughput under load Practical example: soccer player statistics Consider a system analyzing soccer player performance with the following schema:\nCREATE TABLE players ( player_id SERIAL PRIMARY KEY, nationality TEXT, age INT, position TEXT ); CREATE TABLE matches ( match_id SERIAL PRIMARY KEY, match_date DATE, home_team TEXT, away_team TEXT ); CREATE TABLE player_stats ( player_stat_id SERIAL PRIMARY KEY, player_id INT REFERENCES players(player_id), match_id INT REFERENCES matches(match_id), goals INT, assists INT, minutes_played INT ); A query to find top 2000 players by total score:\nSELECT p.player_id, SUM(ps.goals + ps.assists) AS total_score FROM player_stats ps JOIN players p ON ps.player_id = p.player_id GROUP BY p.player_id ORDER BY total_score DESC LIMIT 2000; Analyzing with EXPLAIN Use EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS) to understand query execution:\nBEGIN; SET LOCAL work_mem = \u0026#39;64kB\u0026#39;; EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS) SELECT p.player_id, SUM(ps.goals + ps.assists) AS total_score FROM player_stats ps INNER JOIN players p ON p.player_id = ps.player_id GROUP BY p.player_id ORDER BY total_score DESC LIMIT 2000; COMMIT; With work_mem = 64kB (too low) Execution time: ~82ms Sort Method: external merge Disk: 280kB Multiple sort operations spill to disk Merge Join used instead of Hash Join With work_mem = 4MB (default) Execution time: ~42ms (50% improvement) Sort Method: top-N heapsort Memory: 227kB Hash Join used instead of Merge Join All operations fit in memory Impact on API performance Load testing with k6 demonstrates the real-world impact:\nTest with work_mem = 64kB:\nAverage response time: 108ms p90 latency: 138.63ms Throughput: 63 requests/second Test with work_mem = 4MB:\nAverage response time: 71.77ms p90 latency: 95.3ms (43ms improvement) Throughput: 95 requests/second (50% increase) Configuring work_mem User-level configuration ALTER USER foo SET work_mem=\u0026#39;32MB\u0026#39;; Important: If using connection pools, recycle old sessions for the new configuration to take effect.\nTransaction-level configuration BEGIN; SET LOCAL work_mem = \u0026#39;32MB\u0026#39;; -- Your queries here COMMIT; Memory considerations A single complex query can consume multiple times the work_mem value because:\nMultiple sort operations can each use work_mem Hash joins use work_mem (influenced by hash_mem_multiplier) Merge joins may require sorting Formula to estimate total memory:\nTotal memory ≈ work_mem × (number of sort operations + hash operations) Finding the right value There\u0026rsquo;s no magic formula. Consider:\nAvailable system memory: Don\u0026rsquo;t set so high that PostgreSQL runs out of memory Concurrent connections: Each connection can use work_mem per operation Query patterns: Analyze your slow queries with EXPLAIN Workload characteristics: OLTP vs OLAP have different requirements Recommended approach Start with default (4MB) and monitor Identify slow queries with disk-based operations Gradually increase work_mem for specific users/databases Monitor memory usage and query performance Test thoroughly before applying globally Tools and resources TimescaleDB autotune: Automated tuning tool EXPLAIN visualizers: explain.dalibo.com PostgreSQL source code: Understanding internal algorithms Best practices Monitor first: Use pg_stat_statements to identify slow queries Test incrementally: Don\u0026rsquo;t jump from 4MB to 1GB immediately Use transaction-level settings: For specific heavy queries Consider connection pooling: Limit concurrent connections to control total memory Monitor system memory: Watch for OOM (Out of Memory) errors Conclusion The work_mem parameter is a powerful tool for PostgreSQL performance tuning, but it requires careful consideration of your system\u0026rsquo;s memory, workload, and query patterns. The key is to test, measure, and iterate until you find the optimal value for your use case.\nRemember: TEST. TEST TODAY. TEST TOMORROW. TEST FOREVER. Keep testing until you find an acceptable value that enhances query performance without overwhelming your database server.\n","permalink":"https://pixcave.com/posts/postgresql-work-mem-performance-tuning/","summary":"\u003cp\u003ePostgreSQL\u0026rsquo;s \u003ccode\u003ework_mem\u003c/code\u003e parameter is one of the most impactful yet misunderstood configuration settings for database performance. This post explores how adjusting \u003ccode\u003ework_mem\u003c/code\u003e can dramatically improve query execution times, especially for operations involving sorting, hashing, and joins.\u003c/p\u003e\n\u003ch2 id=\"understanding-work_mem\"\u003eUnderstanding work_mem\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003ework_mem\u003c/code\u003e specifies the amount of memory PostgreSQL can use for internal sort operations and hash tables before writing to temporary disk files. The default value is 4MB, which is conservative to ensure PostgreSQL runs on smaller machines.\u003c/p\u003e","title":"PostgreSQL Performance Tuning: The Power of work_mem"},{"content":"Core settings max.poll.interval.ms sized to processing time; max.poll.records to batch size. fetch.min.bytes/fetch.max.wait.ms to trade latency vs throughput. enable.auto.commit=false; commit sync/async after processing batch. Concurrency Prefer multiple consumer instances over massive max.poll.records. For CPU-bound steps, hand off to bounded executor; avoid blocking poll thread. Ordering \u0026amp; retries Keep partition affinity when ordering matters; use DLT for poison messages. Backoff with jitter on retries; limit attempts per message. Observability Metrics: lag per partition, commit latency, rebalances, processing time, error rates. Log offsets and partition for errors; trace batch sizes. Checklist Poll loop never blocks; work delegated to bounded pool. Commits after successful processing; DLT in place. Lag and rebalance metrics monitored. ","permalink":"https://pixcave.com/posts/java-kafka-consumer-tuning/","summary":"\u003ch2 id=\"core-settings\"\u003eCore settings\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003emax.poll.interval.ms\u003c/code\u003e sized to processing time; \u003ccode\u003emax.poll.records\u003c/code\u003e to batch size.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efetch.min.bytes\u003c/code\u003e/\u003ccode\u003efetch.max.wait.ms\u003c/code\u003e to trade latency vs throughput.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eenable.auto.commit=false\u003c/code\u003e; commit sync/async after processing batch.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"concurrency\"\u003eConcurrency\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrefer multiple consumer instances over massive \u003ccode\u003emax.poll.records\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eFor CPU-bound steps, hand off to bounded executor; avoid blocking poll thread.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ordering--retries\"\u003eOrdering \u0026amp; retries\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep partition affinity when ordering matters; use DLT for poison messages.\u003c/li\u003e\n\u003cli\u003eBackoff with jitter on retries; limit attempts per message.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMetrics: lag per partition, commit latency, rebalances, processing time, error rates.\u003c/li\u003e\n\u003cli\u003eLog offsets and partition for errors; trace batch sizes.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Poll loop never blocks; work delegated to bounded pool.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Commits after successful processing; DLT in place.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Lag and rebalance metrics monitored.\u003c/li\u003e\n\u003c/ul\u003e","title":"Tuning Kafka Consumers (Java)"},{"content":"Designing a REST API that is intuitive, maintainable, and scalable requires following established best practices. Here\u0026rsquo;s a comprehensive guide.\n1. Use Nouns, Not Verbs Good GET /users GET /users/123 POST /users PUT /users/123 DELETE /users/123 Bad GET /getUsers GET /getUserById POST /createUser PUT /updateUser DELETE /deleteUser 2. Use Plural Nouns Good GET /users GET /orders GET /products Bad GET /user GET /order GET /product 3. Use HTTP Methods Correctly // GET - Retrieve resources GET /users // Get all users GET /users/123 // Get specific user // POST - Create new resources POST /users // Create new user // PUT - Update entire resource PUT /users/123 // Replace user // PATCH - Partial update PATCH /users/123 // Update specific fields // DELETE - Remove resources DELETE /users/123 // Delete user 4. Use Proper HTTP Status Codes // Success 200 OK // Successful GET, PUT, PATCH 201 Created // Successful POST 204 No Content // Successful DELETE // Client Errors 400 Bad Request // Invalid request 401 Unauthorized // Authentication required 403 Forbidden // Insufficient permissions 404 Not Found // Resource doesn\u0026#39;t exist 409 Conflict // Resource conflict // Server Errors 500 Internal Server Error 503 Service Unavailable 5. Consistent Response Format { \u0026#34;data\u0026#34;: { \u0026#34;id\u0026#34;: 123, \u0026#34;name\u0026#34;: \u0026#34;John Doe\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;john@example.com\u0026#34; }, \u0026#34;meta\u0026#34;: { \u0026#34;timestamp\u0026#34;: \u0026#34;2024-11-15T10:00:00Z\u0026#34; } } Error Response Format { \u0026#34;error\u0026#34;: { \u0026#34;code\u0026#34;: \u0026#34;VALIDATION_ERROR\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid input data\u0026#34;, \u0026#34;details\u0026#34;: [ { \u0026#34;field\u0026#34;: \u0026#34;email\u0026#34;, \u0026#34;message\u0026#34;: \u0026#34;Invalid email format\u0026#34; } ] } } 6. Versioning URL Versioning /api/v1/users /api/v2/users Header Versioning Accept: application/vnd.api+json;version=1 7. Filtering, Sorting, Pagination GET /users?page=1\u0026amp;limit=20 GET /users?sort=name\u0026amp;order=asc GET /users?status=active\u0026amp;role=admin GET /users?search=john 8. Nested Resources GET /users/123/posts POST /users/123/posts GET /users/123/posts/456 PUT /users/123/posts/456 DELETE /users/123/posts/456 9. Use HTTPS Always use HTTPS in production to encrypt data in transit.\n10. API Documentation Document your API using:\nOpenAPI/Swagger API Blueprint Postman Collections Best Practices Summary Use RESTful conventions Proper HTTP methods and status codes Consistent response formats Version your APIs Implement filtering, sorting, pagination Use HTTPS Document thoroughly Handle errors gracefully Rate limiting Authentication and authorization Conclusion Following these REST API design best practices helps you build:\nIntuitive APIs Maintainable endpoints Scalable systems Developer-friendly interfaces Design with these principles in mind! 🚀\n","permalink":"https://pixcave.com/posts/rest-api-design-best-practices/","summary":"\u003cp\u003eDesigning a REST API that is intuitive, maintainable, and scalable requires following established best practices. Here\u0026rsquo;s a comprehensive guide.\u003c/p\u003e\n\u003ch2 id=\"1-use-nouns-not-verbs\"\u003e1. Use Nouns, Not Verbs\u003c/h2\u003e\n\u003ch3 id=\"good\"\u003eGood\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET    /users\nGET    /users/123\nPOST   /users\nPUT    /users/123\nDELETE /users/123\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"bad\"\u003eBad\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET    /getUsers\nGET    /getUserById\nPOST   /createUser\nPUT    /updateUser\nDELETE /deleteUser\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"2-use-plural-nouns\"\u003e2. Use Plural Nouns\u003c/h2\u003e\n\u003ch3 id=\"good-1\"\u003eGood\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET /users\nGET /orders\nGET /products\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"bad-1\"\u003eBad\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET /user\nGET /order\nGET /product\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"3-use-http-methods-correctly\"\u003e3. Use HTTP Methods Correctly\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// GET - Retrieve resources\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eGET\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e          \u003cspan style=\"color:#75715e\"\u003e// Get all users\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eGET\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e// Get specific user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// POST - Create new resources\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ePOST\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e         \u003cspan style=\"color:#75715e\"\u003e// Create new user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// PUT - Update entire resource\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ePUT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e// Replace user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// PATCH - Partial update\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ePATCH\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e// Update specific fields\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// DELETE - Remove resources\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eDELETE\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e   \u003cspan style=\"color:#75715e\"\u003e// Delete user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-use-proper-http-status-codes\"\u003e4. Use Proper HTTP Status Codes\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Success\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOK\u003c/span\u003e              \u003cspan style=\"color:#75715e\"\u003e// Successful GET, PUT, PATCH\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e201\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCreated\u003c/span\u003e         \u003cspan style=\"color:#75715e\"\u003e// Successful POST\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e204\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eNo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eContent\u003c/span\u003e      \u003cspan style=\"color:#75715e\"\u003e// Successful DELETE\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Client Errors\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e400\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBad\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRequest\u003c/span\u003e     \u003cspan style=\"color:#75715e\"\u003e// Invalid request\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e401\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUnauthorized\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e// Authentication required\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e403\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eForbidden\u003c/span\u003e       \u003cspan style=\"color:#75715e\"\u003e// Insufficient permissions\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e404\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eNot\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eFound\u003c/span\u003e       \u003cspan style=\"color:#75715e\"\u003e// Resource doesn\u0026#39;t exist\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e409\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eConflict\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// Resource conflict\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Server Errors\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e500\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eInternal\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eServer\u003c/span\u003e Error\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e503\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eService\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUnavailable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-consistent-response-format\"\u003e5. Consistent Response Format\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;data\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;John Doe\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;john@example.com\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;meta\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;timestamp\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;2024-11-15T10:00:00Z\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"error-response-format\"\u003eError Response Format\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;VALIDATION_ERROR\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid input data\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;details\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;field\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid email format\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-versioning\"\u003e6. Versioning\u003c/h2\u003e\n\u003ch3 id=\"url-versioning\"\u003eURL Versioning\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/api/v1/users\n/api/v2/users\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"header-versioning\"\u003eHeader Versioning\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eAccept: application/vnd.api+json;version=1\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"7-filtering-sorting-pagination\"\u003e7. Filtering, Sorting, Pagination\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET /users?page=1\u0026amp;limit=20\nGET /users?sort=name\u0026amp;order=asc\nGET /users?status=active\u0026amp;role=admin\nGET /users?search=john\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"8-nested-resources\"\u003e8. Nested Resources\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET    /users/123/posts\nPOST   /users/123/posts\nGET    /users/123/posts/456\nPUT    /users/123/posts/456\nDELETE /users/123/posts/456\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"9-use-https\"\u003e9. Use HTTPS\u003c/h2\u003e\n\u003cp\u003eAlways use HTTPS in production to encrypt data in transit.\u003c/p\u003e","title":"REST API Design Best Practices: Building Production-Ready APIs"},{"content":"Capturing safely Expose /debug/pprof behind auth/VPN; or run curl -sK -H \u0026quot;Authorization: Bearer ...\u0026quot;. CPU profile: go tool pprof http://host/debug/pprof/profile?seconds=30. Heap profile: .../heap; Goroutines: .../goroutine?debug=2. For containers: kubectl port-forward then grab profiles; avoid prod CPU throttle when profiling. Reading CPU profiles Look at flat vs. cumulative time; identify hot functions. Flamegraph: go tool pprof -http=:8081 cpu.pprof. Check GC activity and syscalls; watch for mutex contention. Reading heap profiles Compare live allocations vs. in-use objects; watch large []byte and map growth. Look for leaks via rising heap over time; diff profiles between runs. Goroutine dumps Spot leaked goroutines (blocked on channel/lock/I/O). Common culprits: missing cancel, unbounded worker creation, stuck time.After. Best practices Add pprof only when needed in prod; default on in staging. Sample under load close to real traffic. Keep artifacts: store profiles with build SHA + timestamp; compare after releases. Combine with metrics (alloc rate, GC pauses, goroutines) to validate fixes. ","permalink":"https://pixcave.com/posts/go-pprof-profiling-guide/","summary":"\u003ch2 id=\"capturing-safely\"\u003eCapturing safely\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eExpose \u003ccode\u003e/debug/pprof\u003c/code\u003e behind auth/VPN; or run \u003ccode\u003ecurl -sK -H \u0026quot;Authorization: Bearer ...\u0026quot;\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eCPU profile: \u003ccode\u003ego tool pprof http://host/debug/pprof/profile?seconds=30\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eHeap profile: \u003ccode\u003e.../heap\u003c/code\u003e; Goroutines: \u003ccode\u003e.../goroutine?debug=2\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eFor containers: \u003ccode\u003ekubectl port-forward\u003c/code\u003e then grab profiles; avoid prod CPU throttle when profiling.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"reading-cpu-profiles\"\u003eReading CPU profiles\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLook at flat vs. cumulative time; identify hot functions.\u003c/li\u003e\n\u003cli\u003eFlamegraph: \u003ccode\u003ego tool pprof -http=:8081 cpu.pprof\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eCheck GC activity and syscalls; watch for mutex contention.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"reading-heap-profiles\"\u003eReading heap profiles\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCompare live allocations vs. in-use objects; watch large \u003ccode\u003e[]byte\u003c/code\u003e and map growth.\u003c/li\u003e\n\u003cli\u003eLook for leaks via rising heap over time; diff profiles between runs.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"goroutine-dumps\"\u003eGoroutine dumps\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSpot leaked goroutines (blocked on channel/lock/I/O).\u003c/li\u003e\n\u003cli\u003eCommon culprits: missing cancel, unbounded worker creation, stuck \u003ccode\u003etime.After\u003c/code\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"best-practices\"\u003eBest practices\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAdd \u003ccode\u003epprof\u003c/code\u003e only when needed in prod; default on in staging.\u003c/li\u003e\n\u003cli\u003eSample under load close to real traffic.\u003c/li\u003e\n\u003cli\u003eKeep artifacts: store profiles with build SHA + timestamp; compare after releases.\u003c/li\u003e\n\u003cli\u003eCombine with metrics (alloc rate, GC pauses, goroutines) to validate fixes.\u003c/li\u003e\n\u003c/ul\u003e","title":"Go Profiling in Production with pprof"},{"content":"Microservices communicate through various patterns, each with trade-offs. Understanding when to use synchronous vs asynchronous communication is crucial for building scalable, resilient systems.\nCommunication patterns overview Microservices can communicate through:\nSynchronous: Direct request-response (REST, gRPC) Asynchronous: Message-based (queues, events, pub/sub) Hybrid: Combination of both approaches Synchronous communication REST API Most common pattern for service-to-service communication.\nAdvantages:\nSimple and familiar Language agnostic Easy to debug Good tooling support Disadvantages:\nTight coupling Cascading failures Latency accumulation No guaranteed delivery Example:\n// Service A calling Service B const response = await fetch(\u0026#39;http://service-b/api/users\u0026#39;, { method: \u0026#39;GET\u0026#39;, headers: { \u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39; } }); const users = await response.json(); Best practices:\nUse circuit breakers Implement retries with exponential backoff Set appropriate timeouts Use service discovery gRPC High-performance RPC framework using HTTP/2 and Protocol Buffers.\nAdvantages:\nHigh performance (binary protocol) Strong typing Streaming support Language agnostic Disadvantages:\nLess human-readable Requires code generation HTTP/2 only Example:\n// user.proto syntax = \u0026#34;proto3\u0026#34;; service UserService { rpc GetUser(UserRequest) returns (UserResponse); rpc ListUsers(Empty) returns (stream User); } message UserRequest { string user_id = 1; } message UserResponse { string id = 1; string name = 2; string email = 3; } // Go client conn, _ := grpc.Dial(\u0026#34;service-b:50051\u0026#34;, grpc.WithInsecure()) client := pb.NewUserServiceClient(conn) user, _ := client.GetUser(ctx, \u0026amp;pb.UserRequest{UserId: \u0026#34;123\u0026#34;}) GraphQL Query language for APIs that allows clients to request exactly what they need.\nAdvantages:\nFlexible queries Single endpoint Reduces over-fetching Strong typing Disadvantages:\nComplex queries can be expensive Caching challenges Learning curve Example:\n# Query query { user(id: \u0026#34;123\u0026#34;) { name email posts { title createdAt } } } Asynchronous communication Message queues Services communicate through message brokers.\nPatterns:\nPoint-to-point: One producer, one consumer Pub/Sub: One producer, multiple consumers Advantages:\nDecoupling Resilience (messages persist) Scalability Load leveling Disadvantages:\nEventual consistency Complexity Message ordering challenges Debugging difficulty Example with RabbitMQ:\n// Producer const amqp = require(\u0026#39;amqplib\u0026#39;); const connection = await amqp.connect(\u0026#39;amqp://localhost\u0026#39;); const channel = await connection.createChannel(); await channel.assertQueue(\u0026#39;user.created\u0026#39;, { durable: true }); channel.sendToQueue(\u0026#39;user.created\u0026#39;, Buffer.from(JSON.stringify({ userId: \u0026#39;123\u0026#39;, email: \u0026#39;user@example.com\u0026#39; })), { persistent: true }); // Consumer const channel = await connection.createChannel(); await channel.assertQueue(\u0026#39;user.created\u0026#39;, { durable: true }); channel.consume(\u0026#39;user.created\u0026#39;, (msg) =\u0026gt; { const user = JSON.parse(msg.content.toString()); // Process user creation channel.ack(msg); }, { noAck: false }); Event-driven architecture Services publish events that other services subscribe to.\nExample with Kafka:\n// Producer const { Kafka } = require(\u0026#39;kafkajs\u0026#39;); const kafka = new Kafka({ brokers: [\u0026#39;localhost:9092\u0026#39;] }); const producer = kafka.producer(); await producer.connect(); await producer.send({ topic: \u0026#39;user.events\u0026#39;, messages: [{ key: \u0026#39;user.created\u0026#39;, value: JSON.stringify({ userId: \u0026#39;123\u0026#39;, eventType: \u0026#39;USER_CREATED\u0026#39;, timestamp: new Date().toISOString() }) }] }); // Consumer const consumer = kafka.consumer({ groupId: \u0026#39;user-service\u0026#39; }); await consumer.connect(); await consumer.subscribe({ topic: \u0026#39;user.events\u0026#39; }); await consumer.run({ eachMessage: async ({ topic, partition, message }) =\u0026gt; { const event = JSON.parse(message.value.toString()); // Handle event } }); Choosing the right pattern Use synchronous when: Need immediate response Transactional consistency required Simple request-response flow Low latency critical Examples:\nUser authentication Payment processing Real-time data queries Use asynchronous when: Can tolerate eventual consistency Need to decouple services High throughput required Long-running processes Examples:\nEmail notifications Data synchronization Event logging Background processing Resilience patterns Circuit breaker Prevents cascading failures:\nconst CircuitBreaker = require(\u0026#39;opossum\u0026#39;); const options = { timeout: 3000, errorThresholdPercentage: 50, resetTimeout: 30000 }; const breaker = new CircuitBreaker(serviceCall, options); breaker.on(\u0026#39;open\u0026#39;, () =\u0026gt; { console.log(\u0026#39;Circuit breaker opened\u0026#39;); }); breaker.on(\u0026#39;halfOpen\u0026#39;, () =\u0026gt; { console.log(\u0026#39;Circuit breaker half-open\u0026#39;); }); breaker.on(\u0026#39;close\u0026#39;, () =\u0026gt; { console.log(\u0026#39;Circuit breaker closed\u0026#39;); }); Retry with exponential backoff async function retryWithBackoff(fn, maxRetries = 3) { for (let i = 0; i \u0026lt; maxRetries; i++) { try { return await fn(); } catch (error) { if (i === maxRetries - 1) throw error; await sleep(Math.pow(2, i) * 1000); } } } Bulkhead pattern Isolate resources to prevent failures from spreading:\n// Use separate connection pools const userServicePool = new Pool({ max: 10 }); const orderServicePool = new Pool({ max: 10 }); Service mesh For complex microservices, consider a service mesh:\nBenefits:\nAutomatic retries Circuit breaking Load balancing Security (mTLS) Observability Popular options:\nIstio Linkerd Consul Connect Best practices Synchronous communication Set timeouts: Always set reasonable timeouts Use circuit breakers: Prevent cascading failures Implement retries: With exponential backoff Service discovery: Use service registry Health checks: Monitor service availability Asynchronous communication Idempotency: Design handlers to be idempotent Message ordering: Handle ordering if required Dead letter queues: Handle failed messages Message versioning: Support schema evolution Monitoring: Track message processing times General API versioning: Support multiple API versions Documentation: Document all APIs Monitoring: Track latency, errors, throughput Testing: Test communication patterns Security: Use authentication and authorization Conclusion Choosing the right communication pattern depends on your requirements for consistency, latency, and coupling. Use synchronous communication for immediate responses and transactional needs, and asynchronous for decoupling and scalability. Often, a hybrid approach works best.\nRemember: There\u0026rsquo;s no one-size-fits-all solution. Design your communication patterns based on your specific use cases and requirements.\n","permalink":"https://pixcave.com/posts/microservices-communication-patterns/","summary":"\u003cp\u003eMicroservices communicate through various patterns, each with trade-offs. Understanding when to use synchronous vs asynchronous communication is crucial for building scalable, resilient systems.\u003c/p\u003e\n\u003ch2 id=\"communication-patterns-overview\"\u003eCommunication patterns overview\u003c/h2\u003e\n\u003cp\u003eMicroservices can communicate through:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSynchronous\u003c/strong\u003e: Direct request-response (REST, gRPC)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAsynchronous\u003c/strong\u003e: Message-based (queues, events, pub/sub)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHybrid\u003c/strong\u003e: Combination of both approaches\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"synchronous-communication\"\u003eSynchronous communication\u003c/h2\u003e\n\u003ch3 id=\"rest-api\"\u003eREST API\u003c/h3\u003e\n\u003cp\u003eMost common pattern for service-to-service communication.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAdvantages\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSimple and familiar\u003c/li\u003e\n\u003cli\u003eLanguage agnostic\u003c/li\u003e\n\u003cli\u003eEasy to debug\u003c/li\u003e\n\u003cli\u003eGood tooling support\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eDisadvantages\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eTight coupling\u003c/li\u003e\n\u003cli\u003eCascading failures\u003c/li\u003e\n\u003cli\u003eLatency accumulation\u003c/li\u003e\n\u003cli\u003eNo guaranteed delivery\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eExample\u003c/strong\u003e:\u003c/p\u003e","title":"Microservices Communication Patterns: Synchronous vs Asynchronous"},{"content":"Core settings Sliding window (count/time), failure rate threshold, slow-call threshold, minimum calls. Wait duration in open state; half-open permitted calls; automatic transition. Patterns Wrap HTTP/DB/queue clients; combine with timeouts/retries/bulkheads. Tune per dependency; differentiate fast-fail vs. tolerant paths. Provide fallback only when safe/idempotent. Observability Export metrics: state changes, calls/success/failure/slow, not permitted count. Log state transitions; add exemplars linking to traces. Alert on frequent open/half-open oscillation. Checklist Per-downstream breaker with tailored thresholds. Timeouts and retries composed correctly (timeout → breaker → retry). Metrics/logs/traces wired; alerts on open rate. ","permalink":"https://pixcave.com/posts/java-resilience4j-circuit-breakers/","summary":"\u003ch2 id=\"core-settings\"\u003eCore settings\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSliding window (count/time), failure rate threshold, slow-call threshold, minimum calls.\u003c/li\u003e\n\u003cli\u003eWait duration in open state; half-open permitted calls; automatic transition.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"patterns\"\u003ePatterns\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWrap HTTP/DB/queue clients; combine with timeouts/retries/bulkheads.\u003c/li\u003e\n\u003cli\u003eTune per dependency; differentiate fast-fail vs. tolerant paths.\u003c/li\u003e\n\u003cli\u003eProvide fallback only when safe/idempotent.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eExport metrics: state changes, calls/success/failure/slow, not permitted count.\u003c/li\u003e\n\u003cli\u003eLog state transitions; add exemplars linking to traces.\u003c/li\u003e\n\u003cli\u003eAlert on frequent open/half-open oscillation.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Per-downstream breaker with tailored thresholds.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Timeouts and retries composed correctly (timeout → breaker → retry).\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics/logs/traces wired; alerts on open rate.\u003c/li\u003e\n\u003c/ul\u003e","title":"Circuit Breakers with Resilience4j"},{"content":"Database performance is critical for application scalability. Here are proven optimization techniques.\n1. Indexing Strategy When to Index -- Index frequently queried columns CREATE INDEX idx_user_email ON users(email); -- Index foreign keys CREATE INDEX idx_post_user_id ON posts(user_id); -- Composite indexes for multi-column queries CREATE INDEX idx_user_status_role ON users(status, role); When NOT to Index Columns with low cardinality (few unique values) Frequently updated columns Small tables (\u0026lt; 1000 rows) 2. Query Optimization Avoid SELECT * -- Bad SELECT * FROM users WHERE id = 123; -- Good SELECT id, name, email FROM users WHERE id = 123; Use LIMIT -- Always limit large result sets SELECT * FROM posts ORDER BY created_at DESC LIMIT 20; Avoid N+1 Queries // Bad: N+1 queries users.forEach(user =\u0026gt; { const posts = db.query(\u0026#39;SELECT * FROM posts WHERE user_id = ?\u0026#39;, [user.id]); }); // Good: Single query with JOIN const usersWithPosts = db.query(` SELECT u.*, p.* FROM users u LEFT JOIN posts p ON u.id = p.user_id `); 3. Connection Pooling // Configure connection pool const pool = mysql.createPool({ connectionLimit: 10, host: \u0026#39;localhost\u0026#39;, user: \u0026#39;user\u0026#39;, password: \u0026#39;password\u0026#39;, database: \u0026#39;mydb\u0026#39;, waitForConnections: true, queueLimit: 0 }); 4. Caching Application-Level Caching // Cache frequently accessed data const cache = new Map(); async function getUser(id) { if (cache.has(id)) { return cache.get(id); } const user = await db.query(\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;, [id]); cache.set(id, user); return user; } Query Result Caching -- Use query cache (MySQL) SET GLOBAL query_cache_size = 67108864; SET GLOBAL query_cache_type = 1; 5. Database Schema Optimization Normalize Properly -- Avoid over-normalization -- Balance between normalization and performance Use Appropriate Data Types -- Use smallest appropriate type TINYINT instead of INT for small numbers VARCHAR(255) instead of TEXT when possible DATE instead of DATETIME when time not needed 6. Partitioning -- Partition large tables by date CREATE TABLE logs ( id INT, created_at DATE, data TEXT ) PARTITION BY RANGE (YEAR(created_at)) ( PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025), PARTITION p2025 VALUES LESS THAN (2026) ); 7. Query Analysis EXPLAIN Plan EXPLAIN SELECT * FROM users WHERE email = \u0026#39;test@example.com\u0026#39;; Slow Query Log -- Enable slow query log SET GLOBAL slow_query_log = \u0026#39;ON\u0026#39;; SET GLOBAL long_query_time = 1; 8. Batch Operations // Bad: Multiple individual inserts users.forEach(user =\u0026gt; { db.query(\u0026#39;INSERT INTO users (name, email) VALUES (?, ?)\u0026#39;, [user.name, user.email]); }); // Good: Batch insert const values = users.map(u =\u0026gt; [u.name, u.email]); db.query(\u0026#39;INSERT INTO users (name, email) VALUES ?\u0026#39;, [values]); 9. Database Maintenance Regular Vacuuming (PostgreSQL) VACUUM ANALYZE; Optimize Tables (MySQL) OPTIMIZE TABLE users; 10. Monitoring Monitor query performance Track slow queries Monitor connection pool usage Watch for table locks Monitor disk I/O Best Practices Index strategically Optimize queries Use connection pooling Implement caching Normalize appropriately Use appropriate data types Partition large tables Analyze query performance Batch operations Regular maintenance Conclusion Database optimization requires:\nStrategic indexing Query optimization Proper caching Regular monitoring Maintenance routines Optimize systematically for better performance! 🚀\n","permalink":"https://pixcave.com/posts/database-optimization-techniques/","summary":"\u003cp\u003eDatabase performance is critical for application scalability. Here are proven optimization techniques.\u003c/p\u003e\n\u003ch2 id=\"1-indexing-strategy\"\u003e1. Indexing Strategy\u003c/h2\u003e\n\u003ch3 id=\"when-to-index\"\u003eWhen to Index\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Index frequently queried columns\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_user_email \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e users(email);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Index foreign keys\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_post_user_id \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e posts(user_id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Composite indexes for multi-column queries\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_user_status_role \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e users(status, \u003cspan style=\"color:#66d9ef\"\u003erole\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"when-not-to-index\"\u003eWhen NOT to Index\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eColumns with low cardinality (few unique values)\u003c/li\u003e\n\u003cli\u003eFrequently updated columns\u003c/li\u003e\n\u003cli\u003eSmall tables (\u0026lt; 1000 rows)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-query-optimization\"\u003e2. Query Optimization\u003c/h2\u003e\n\u003ch3 id=\"avoid-select-\"\u003eAvoid SELECT *\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Bad\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Good\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e id, name, email \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e123\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-limit\"\u003eUse LIMIT\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Always limit large result sets\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e posts \u003cspan style=\"color:#66d9ef\"\u003eORDER\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eBY\u003c/span\u003e created_at \u003cspan style=\"color:#66d9ef\"\u003eDESC\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eLIMIT\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"avoid-n1-queries\"\u003eAvoid N+1 Queries\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: N+1 queries\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eforEach\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SELECT * FROM posts WHERE user_id = ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Single query with JOIN\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eusersWithPosts\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  SELECT u.*, p.* \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  FROM users u\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  LEFT JOIN posts p ON u.id = p.user_id\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-connection-pooling\"\u003e3. Connection Pooling\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Configure connection pool\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epool\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emysql\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreatePool\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econnectionLimit\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ehost\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;localhost\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;user\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edatabase\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;mydb\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewaitForConnections\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003equeueLimit\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-caching\"\u003e4. Caching\u003c/h2\u003e\n\u003ch3 id=\"application-level-caching\"\u003eApplication-Level Caching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Cache frequently accessed data\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecache\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMap\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ecache\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehas\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecache\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecache\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eset\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"query-result-caching\"\u003eQuery Result Caching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Use query cache (MySQL)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eSET\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eGLOBAL\u003c/span\u003e query_cache_size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e67108864\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSET\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eGLOBAL\u003c/span\u003e query_cache_type \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-database-schema-optimization\"\u003e5. Database Schema Optimization\u003c/h2\u003e\n\u003ch3 id=\"normalize-properly\"\u003eNormalize Properly\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Avoid over-normalization\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Balance between normalization and performance\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-appropriate-data-types\"\u003eUse Appropriate Data Types\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Use smallest appropriate type\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eTINYINT \u003cspan style=\"color:#66d9ef\"\u003einstead\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eof\u003c/span\u003e INT \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e small numbers\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eVARCHAR(\u003cspan style=\"color:#ae81ff\"\u003e255\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003einstead\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eof\u003c/span\u003e TEXT \u003cspan style=\"color:#66d9ef\"\u003ewhen\u003c/span\u003e possible\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDATE \u003cspan style=\"color:#66d9ef\"\u003einstead\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eof\u003c/span\u003e DATETIME \u003cspan style=\"color:#66d9ef\"\u003ewhen\u003c/span\u003e time \u003cspan style=\"color:#66d9ef\"\u003enot\u003c/span\u003e needed\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-partitioning\"\u003e6. Partitioning\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Partition large tables by date\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTABLE\u003c/span\u003e logs (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  id INT,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  created_at DATE,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003edata\u003c/span\u003e TEXT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e) PARTITION \u003cspan style=\"color:#66d9ef\"\u003eBY\u003c/span\u003e RANGE (\u003cspan style=\"color:#66d9ef\"\u003eYEAR\u003c/span\u003e(created_at)) (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PARTITION p2023 \u003cspan style=\"color:#66d9ef\"\u003eVALUES\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eLESS\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTHAN\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e2024\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PARTITION p2024 \u003cspan style=\"color:#66d9ef\"\u003eVALUES\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eLESS\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTHAN\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e2025\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  PARTITION p2025 \u003cspan style=\"color:#66d9ef\"\u003eVALUES\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eLESS\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eTHAN\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e2026\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-query-analysis\"\u003e7. Query Analysis\u003c/h2\u003e\n\u003ch3 id=\"explain-plan\"\u003eEXPLAIN Plan\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eEXPLAIN\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e email \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"slow-query-log\"\u003eSlow Query Log\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Enable slow query log\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eSET\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eGLOBAL\u003c/span\u003e slow_query_log \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ON\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSET\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eGLOBAL\u003c/span\u003e long_query_time \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"8-batch-operations\"\u003e8. Batch Operations\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Multiple individual inserts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eforEach\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;INSERT INTO users (name, email) VALUES (?, ?)\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Batch insert\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e =\u0026gt; [\u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eu\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;INSERT INTO users (name, email) VALUES ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"9-database-maintenance\"\u003e9. Database Maintenance\u003c/h2\u003e\n\u003ch3 id=\"regular-vacuuming-postgresql\"\u003eRegular Vacuuming (PostgreSQL)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eVACUUM\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eANALYZE\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"optimize-tables-mysql\"\u003eOptimize Tables (MySQL)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOPTIMIZE \u003cspan style=\"color:#66d9ef\"\u003eTABLE\u003c/span\u003e users;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"10-monitoring\"\u003e10. Monitoring\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMonitor query performance\u003c/li\u003e\n\u003cli\u003eTrack slow queries\u003c/li\u003e\n\u003cli\u003eMonitor connection pool usage\u003c/li\u003e\n\u003cli\u003eWatch for table locks\u003c/li\u003e\n\u003cli\u003eMonitor disk I/O\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eIndex strategically\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOptimize queries\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse connection pooling\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement caching\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNormalize appropriately\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse appropriate data types\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePartition large tables\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAnalyze query performance\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBatch operations\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRegular maintenance\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eDatabase optimization requires:\u003c/p\u003e","title":"Database Optimization Techniques: Performance Tuning Guide"},{"content":"Queue types Prefer quorum queues for HA; classic for transient/high-throughput if loss acceptable. Set durability/persistence appropriately; avoid auto-delete for critical flows. Flow control Enable publisher confirms; set mandatory flag to catch unroutable messages. Use basic.qos to bound unacked messages; prefetch tuned per consumer. Watch memory/flow events; avoid oversized messages—use blob storage for big payloads. Topology \u0026amp; ops Mirror/quorum across AZs; avoid single-node SPOF. Use consistent hash/partitioning for hot-key spreading. Metrics: publish/consume rates, unacked count, queue depth, confirm latency, blocked connections. Checklist Queue type chosen (quorum vs classic) per workload. Publisher confirms + unroutable handling. Prefetch/qos tuned; consumers idempotent. Monitoring/alerts on depth, unacked, flow control. ","permalink":"https://pixcave.com/posts/mq-rabbitmq-high-availability/","summary":"\u003ch2 id=\"queue-types\"\u003eQueue types\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrefer quorum queues for HA; classic for transient/high-throughput if loss acceptable.\u003c/li\u003e\n\u003cli\u003eSet durability/persistence appropriately; avoid auto-delete for critical flows.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"flow-control\"\u003eFlow control\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEnable publisher confirms; set mandatory flag to catch unroutable messages.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003ebasic.qos\u003c/code\u003e to bound unacked messages; prefetch tuned per consumer.\u003c/li\u003e\n\u003cli\u003eWatch memory/flow events; avoid oversized messages—use blob storage for big payloads.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"topology--ops\"\u003eTopology \u0026amp; ops\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMirror/quorum across AZs; avoid single-node SPOF.\u003c/li\u003e\n\u003cli\u003eUse consistent hash/partitioning for hot-key spreading.\u003c/li\u003e\n\u003cli\u003eMetrics: publish/consume rates, unacked count, queue depth, confirm latency, blocked connections.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Queue type chosen (quorum vs classic) per workload.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Publisher confirms + unroutable handling.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Prefetch/qos tuned; consumers idempotent.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Monitoring/alerts on depth, unacked, flow control.\u003c/li\u003e\n\u003c/ul\u003e","title":"RabbitMQ High Availability \u0026 Tuning"},{"content":"Choosing G1: balanced latency/throughput for heaps 4–64GB; predictable pauses. ZGC: sub-10ms pauses on large heaps; great for latency-sensitive APIs; slightly higher CPU. Baseline flags G1: -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch ZGC: -XX:+UseZGC -XX:+ZGenerational -XX:+AlwaysPreTouch Set -Xms = -Xmx for stable footprint; size heap from prod RSS data. Metrics to watch Pause p95/p99, GC CPU %, allocation rate, remembered set size (G1), heap occupancy. STW reasons: promotion failure, humongous allocations (G1), metaspace growth. Common fixes Reduce humongous allocations: avoid giant byte[]; use chunked buffers. Lower pause targets only after measuring; avoid over-constraining MaxGCPauseMillis. Cap thread counts: -XX:ParallelGCThreads, -XX:ConcGCThreads if CPU saturated. For ZGC, ensure kernel pages hugepage-friendly; watch NUMA pinning. Checklist Heap sized from live data; -Xms = -Xmx. GC logs on (JDK 17+): -Xlog:gc*:tags,level,time,uptime:file=gc.log:utctime,filesize=20M,files=10 Dashboards for pause/CPU/allocation. Load test changes before prod; compare pause histograms release to release. ","permalink":"https://pixcave.com/posts/java-g1-zgc-tuning/","summary":"\u003ch2 id=\"choosing\"\u003eChoosing\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eG1: balanced latency/throughput for heaps 4–64GB; predictable pauses.\u003c/li\u003e\n\u003cli\u003eZGC: sub-10ms pauses on large heaps; great for latency-sensitive APIs; slightly higher CPU.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"baseline-flags\"\u003eBaseline flags\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eG1: \u003ccode\u003e-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eZGC: \u003ccode\u003e-XX:+UseZGC -XX:+ZGenerational -XX:+AlwaysPreTouch\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eSet \u003ccode\u003e-Xms = -Xmx\u003c/code\u003e for stable footprint; size heap from prod RSS data.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"metrics-to-watch\"\u003eMetrics to watch\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePause p95/p99, GC CPU %, allocation rate, remembered set size (G1), heap occupancy.\u003c/li\u003e\n\u003cli\u003eSTW reasons: promotion failure, humongous allocations (G1), metaspace growth.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"common-fixes\"\u003eCommon fixes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eReduce humongous allocations: avoid giant \u003ccode\u003ebyte[]\u003c/code\u003e; use chunked buffers.\u003c/li\u003e\n\u003cli\u003eLower pause targets only after measuring; avoid over-constraining \u003ccode\u003eMaxGCPauseMillis\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eCap thread counts: \u003ccode\u003e-XX:ParallelGCThreads\u003c/code\u003e, \u003ccode\u003e-XX:ConcGCThreads\u003c/code\u003e if CPU saturated.\u003c/li\u003e\n\u003cli\u003eFor ZGC, ensure kernel pages hugepage-friendly; watch NUMA pinning.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Heap sized from live data; \u003ccode\u003e-Xms = -Xmx\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e GC logs on (JDK 17+): \u003ccode\u003e-Xlog:gc*:tags,level,time,uptime:file=gc.log:utctime,filesize=20M,files=10\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Dashboards for pause/CPU/allocation.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Load test changes before prod; compare pause histograms release to release.\u003c/li\u003e\n\u003c/ul\u003e","title":"Java GC Tuning: G1 and ZGC in Practice"},{"content":"Sizing Pool size ≈ CPU cores * 2–4 per service instance; avoid per-request opens. For PgBouncer tx-mode: disable session features; avoid session-prepared statements. Timeouts \u0026amp; limits Set ConnMaxLifetime, ConnMaxIdleTime, MaxOpenConns, MaxIdleConns. Add statement timeouts; enforce context deadlines on queries. Instrumentation Track pool acquire latency, in-use/idle, wait count, timeouts. Log slow queries; sample EXPLAIN ANALYZE in staging for heavy ones. Hygiene Use prepared statements judiciously; reuse sqlx.Named/pgx prepared for hot paths. Prefer keyset pagination; cap result sizes; parameterize everything. Checklist Pool sized and monitored. Query timeouts set; slow logs reviewed. No per-request connections; connections closed via context cancellation. ","permalink":"https://pixcave.com/posts/go-sqlx-pgx-pooling-patterns/","summary":"\u003ch2 id=\"sizing\"\u003eSizing\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePool size ≈ CPU cores * 2–4 per service instance; avoid per-request opens.\u003c/li\u003e\n\u003cli\u003eFor PgBouncer tx-mode: disable session features; avoid session-prepared statements.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"timeouts--limits\"\u003eTimeouts \u0026amp; limits\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet \u003ccode\u003eConnMaxLifetime\u003c/code\u003e, \u003ccode\u003eConnMaxIdleTime\u003c/code\u003e, \u003ccode\u003eMaxOpenConns\u003c/code\u003e, \u003ccode\u003eMaxIdleConns\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eAdd statement timeouts; enforce \u003ccode\u003econtext\u003c/code\u003e deadlines on queries.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"instrumentation\"\u003eInstrumentation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eTrack pool acquire latency, in-use/idle, wait count, timeouts.\u003c/li\u003e\n\u003cli\u003eLog slow queries; sample \u003ccode\u003eEXPLAIN ANALYZE\u003c/code\u003e in staging for heavy ones.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"hygiene\"\u003eHygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse prepared statements judiciously; reuse \u003ccode\u003esqlx.Named\u003c/code\u003e/pgx prepared for hot paths.\u003c/li\u003e\n\u003cli\u003ePrefer keyset pagination; cap result sizes; parameterize everything.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Pool sized and monitored.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Query timeouts set; slow logs reviewed.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e No per-request connections; connections closed via context cancellation.\u003c/li\u003e\n\u003c/ul\u003e","title":"Go Database Pooling Patterns (sqlx/pgx)"},{"content":"Phases refresher timers → pending → idle/prepare → poll → check → close callbacks. Microtasks (Promises/queueMicrotask) run after each phase; process.nextTick runs before microtasks. Pitfalls Long JS on main thread blocks poll → delays I/O; move CPU work to worker threads. nextTick storms can starve I/O; prefer setImmediate when deferring. Unhandled rejections crash (from Node 15+ default); handle globally in prod. Debugging NODE_DEBUG=async_hooks or --trace-events-enabled --trace-event-categories node.async_hooks. Measure event loop lag: perf_hooks.monitorEventLoopDelay(). Profile CPU with node --inspect + Chrome DevTools; use flamegraphs for hotspots. Practices Limit synchronous JSON/crypto/zlib; offload to worker threads or native modules. Keep microtask chains short; avoid deep promise recursion. Use AbortController for cancellable I/O; always clear timers. Checklist Monitor event loop lag \u0026amp; heap usage. Worker pool sized for CPU tasks; main loop kept light. Errors and rejections centrally handled; graceful shutdown in place. ","permalink":"https://pixcave.com/posts/node-event-loop-internals-2024/","summary":"\u003ch2 id=\"phases-refresher\"\u003ePhases refresher\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003etimers → pending → idle/prepare → poll → check → close callbacks.\u003c/li\u003e\n\u003cli\u003eMicrotasks (Promises/\u003ccode\u003equeueMicrotask\u003c/code\u003e) run after each phase; \u003ccode\u003eprocess.nextTick\u003c/code\u003e runs before microtasks.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"pitfalls\"\u003ePitfalls\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLong JS on main thread blocks poll → delays I/O; move CPU work to worker threads.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003enextTick\u003c/code\u003e storms can starve I/O; prefer \u003ccode\u003esetImmediate\u003c/code\u003e when deferring.\u003c/li\u003e\n\u003cli\u003eUnhandled rejections crash (from Node 15+ default); handle globally in prod.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"debugging\"\u003eDebugging\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eNODE_DEBUG=async_hooks\u003c/code\u003e or \u003ccode\u003e--trace-events-enabled --trace-event-categories node.async_hooks\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eMeasure event loop lag: \u003ccode\u003eperf_hooks.monitorEventLoopDelay()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eProfile CPU with \u003ccode\u003enode --inspect\u003c/code\u003e + Chrome DevTools; use flamegraphs for hotspots.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"practices\"\u003ePractices\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLimit synchronous JSON/crypto/zlib; offload to worker threads or native modules.\u003c/li\u003e\n\u003cli\u003eKeep microtask chains short; avoid deep promise recursion.\u003c/li\u003e\n\u003cli\u003eUse AbortController for cancellable I/O; always clear timers.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Monitor event loop lag \u0026amp; heap usage.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Worker pool sized for CPU tasks; main loop kept light.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Errors and rejections centrally handled; graceful shutdown in place.\u003c/li\u003e\n\u003c/ul\u003e","title":"Node.js Event Loop Internals (2024)"},{"content":"Choosing between microservices and monolithic architecture is a critical decision. Here\u0026rsquo;s how to make the right choice.\nMonolithic Architecture Characteristics Single codebase Single deployment unit Shared database Tightly coupled components Advantages // Simple development // Easy to test // Straightforward deployment // Shared code and data Disadvantages Hard to scale individual components Technology lock-in Deployment risk (all or nothing) Difficult to maintain as it grows Microservices Architecture Characteristics Multiple independent services Separate deployments Service-specific databases Loosely coupled via APIs Advantages Independent scaling Technology diversity Fault isolation Team autonomy Disadvantages Increased complexity Network latency Data consistency challenges Operational overhead When to Choose Monolith Start with Monolith If: Small team (\u0026lt; 10 developers) Simple application Rapid prototyping Limited resources Unclear requirements // Good for startups // MVP development // Small to medium applications When to Choose Microservices Consider Microservices If: Large team (\u0026gt; 50 developers) Complex domain Different scaling needs Multiple teams Clear service boundaries // Good for large organizations // Complex systems // Different technology needs Migration Strategy Strangler Fig Pattern // Gradually replace monolith // Extract services incrementally // Keep monolith running during migration Steps Identify service boundaries Extract one service at a time Maintain backward compatibility Monitor and iterate Best Practices For Monoliths Keep modules loosely coupled Use clear boundaries Plan for future extraction Maintain clean architecture For Microservices Define clear service boundaries Implement proper API contracts Use service mesh for communication Implement distributed tracing Handle failures gracefully Common Pitfalls Microservices Anti-patterns Too many small services Distributed monolith Shared databases Synchronous communication everywhere Monolith Anti-patterns God classes Tight coupling No module boundaries Big ball of mud Conclusion Start with monolith when:\nBuilding MVP Small team Simple requirements Move to microservices when:\nClear service boundaries Different scaling needs Large team Complex domain Key principle: Choose based on your current needs, not future speculation. You can always migrate later! 🚀\n","permalink":"https://pixcave.com/posts/microservices-vs-monolith/","summary":"\u003cp\u003eChoosing between microservices and monolithic architecture is a critical decision. Here\u0026rsquo;s how to make the right choice.\u003c/p\u003e\n\u003ch2 id=\"monolithic-architecture\"\u003eMonolithic Architecture\u003c/h2\u003e\n\u003ch3 id=\"characteristics\"\u003eCharacteristics\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eSingle codebase\u003c/li\u003e\n\u003cli\u003eSingle deployment unit\u003c/li\u003e\n\u003cli\u003eShared database\u003c/li\u003e\n\u003cli\u003eTightly coupled components\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"advantages\"\u003eAdvantages\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Simple development\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Easy to test\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Straightforward deployment\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Shared code and data\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"disadvantages\"\u003eDisadvantages\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eHard to scale individual components\u003c/li\u003e\n\u003cli\u003eTechnology lock-in\u003c/li\u003e\n\u003cli\u003eDeployment risk (all or nothing)\u003c/li\u003e\n\u003cli\u003eDifficult to maintain as it grows\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"microservices-architecture\"\u003eMicroservices Architecture\u003c/h2\u003e\n\u003ch3 id=\"characteristics-1\"\u003eCharacteristics\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eMultiple independent services\u003c/li\u003e\n\u003cli\u003eSeparate deployments\u003c/li\u003e\n\u003cli\u003eService-specific databases\u003c/li\u003e\n\u003cli\u003eLoosely coupled via APIs\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"advantages-1\"\u003eAdvantages\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eIndependent scaling\u003c/li\u003e\n\u003cli\u003eTechnology diversity\u003c/li\u003e\n\u003cli\u003eFault isolation\u003c/li\u003e\n\u003cli\u003eTeam autonomy\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"disadvantages-1\"\u003eDisadvantages\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eIncreased complexity\u003c/li\u003e\n\u003cli\u003eNetwork latency\u003c/li\u003e\n\u003cli\u003eData consistency challenges\u003c/li\u003e\n\u003cli\u003eOperational overhead\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"when-to-choose-monolith\"\u003eWhen to Choose Monolith\u003c/h2\u003e\n\u003ch3 id=\"start-with-monolith-if\"\u003eStart with Monolith If:\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSmall team\u003c/strong\u003e (\u0026lt; 10 developers)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSimple application\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRapid prototyping\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLimited resources\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUnclear requirements\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good for startups\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// MVP development\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Small to medium applications\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"when-to-choose-microservices\"\u003eWhen to Choose Microservices\u003c/h2\u003e\n\u003ch3 id=\"consider-microservices-if\"\u003eConsider Microservices If:\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eLarge team\u003c/strong\u003e (\u0026gt; 50 developers)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eComplex domain\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDifferent scaling needs\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMultiple teams\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eClear service boundaries\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good for large organizations\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Complex systems\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Different technology needs\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"migration-strategy\"\u003eMigration Strategy\u003c/h2\u003e\n\u003ch3 id=\"strangler-fig-pattern\"\u003eStrangler Fig Pattern\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Gradually replace monolith\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Extract services incrementally\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Keep monolith running during migration\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"steps\"\u003eSteps\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eIdentify service boundaries\u003c/li\u003e\n\u003cli\u003eExtract one service at a time\u003c/li\u003e\n\u003cli\u003eMaintain backward compatibility\u003c/li\u003e\n\u003cli\u003eMonitor and iterate\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003ch3 id=\"for-monoliths\"\u003eFor Monoliths\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eKeep modules loosely coupled\u003c/li\u003e\n\u003cli\u003eUse clear boundaries\u003c/li\u003e\n\u003cli\u003ePlan for future extraction\u003c/li\u003e\n\u003cli\u003eMaintain clean architecture\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"for-microservices\"\u003eFor Microservices\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eDefine clear service boundaries\u003c/li\u003e\n\u003cli\u003eImplement proper API contracts\u003c/li\u003e\n\u003cli\u003eUse service mesh for communication\u003c/li\u003e\n\u003cli\u003eImplement distributed tracing\u003c/li\u003e\n\u003cli\u003eHandle failures gracefully\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"common-pitfalls\"\u003eCommon Pitfalls\u003c/h2\u003e\n\u003ch3 id=\"microservices-anti-patterns\"\u003eMicroservices Anti-patterns\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eToo many small services\u003c/li\u003e\n\u003cli\u003eDistributed monolith\u003c/li\u003e\n\u003cli\u003eShared databases\u003c/li\u003e\n\u003cli\u003eSynchronous communication everywhere\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"monolith-anti-patterns\"\u003eMonolith Anti-patterns\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eGod classes\u003c/li\u003e\n\u003cli\u003eTight coupling\u003c/li\u003e\n\u003cli\u003eNo module boundaries\u003c/li\u003e\n\u003cli\u003eBig ball of mud\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eStart with monolith\u003c/strong\u003e when:\u003c/p\u003e","title":"Microservices vs Monolith: Choosing the Right Architecture"},{"content":"Elasticsearch is a powerful search and analytics engine, but optimizing it for production requires understanding indexing strategies, query patterns, and cluster configuration. This guide covers essential optimization techniques.\nCluster architecture Node roles Configure nodes with specific roles:\n# Master node node.roles: [master] # Data node node.roles: [data] # Ingest node node.roles: [ingest] # Coordinating node (default) node.roles: [] # No specific role Shard strategy Primary shards: Set at index creation (cannot be changed)\nPUT /my_index { \u0026#34;settings\u0026#34;: { \u0026#34;number_of_shards\u0026#34;: 3, \u0026#34;number_of_replicas\u0026#34;: 1 } } Best practices:\nAim for 10-50GB per shard Calculate: shards = (total_data_size / 50GB) Consider future growth (2-3x current size) Indexing optimization Bulk indexing Use bulk API for efficient indexing:\n// Node.js example const { Client } = require(\u0026#39;@elastic/elasticsearch\u0026#39;); const client = new Client({ node: \u0026#39;http://localhost:9200\u0026#39; }); async function bulkIndex(documents) { const body = documents.flatMap(doc =\u0026gt; [ { index: { _index: \u0026#39;my_index\u0026#39; } }, doc ]); const response = await client.bulk({ body }); return response; } Best practices:\nBatch size: 1,000-5,000 documents Monitor bulk response for errors Use refresh=false for large imports Index settings Optimize index settings for your use case:\nPUT /my_index { \u0026#34;settings\u0026#34;: { \u0026#34;number_of_shards\u0026#34;: 3, \u0026#34;number_of_replicas\u0026#34;: 1, \u0026#34;refresh_interval\u0026#34;: \u0026#34;30s\u0026#34;, // Reduce refresh frequency \u0026#34;index.translog.durability\u0026#34;: \u0026#34;async\u0026#34;, // For better write performance \u0026#34;index.translog.sync_interval\u0026#34;: \u0026#34;5s\u0026#34; } } Mapping optimization Define explicit mappings:\nPUT /my_index/_mapping { \u0026#34;properties\u0026#34;: { \u0026#34;title\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;text\u0026#34;, \u0026#34;analyzer\u0026#34;: \u0026#34;standard\u0026#34;, \u0026#34;fields\u0026#34;: { \u0026#34;keyword\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;keyword\u0026#34; } } }, \u0026#34;created_at\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;date\u0026#34; }, \u0026#34;status\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;keyword\u0026#34; // Use keyword for exact matches } } } Query optimization Use filters instead of queries Filters are cached and faster:\nGET /my_index/_search { \u0026#34;query\u0026#34;: { \u0026#34;bool\u0026#34;: { \u0026#34;filter\u0026#34;: [ // Use filter for exact matches { \u0026#34;term\u0026#34;: { \u0026#34;status\u0026#34;: \u0026#34;active\u0026#34; } }, { \u0026#34;range\u0026#34;: { \u0026#34;created_at\u0026#34;: { \u0026#34;gte\u0026#34;: \u0026#34;2024-01-01\u0026#34; } } } ], \u0026#34;must\u0026#34;: [ // Use must for relevance scoring { \u0026#34;match\u0026#34;: { \u0026#34;title\u0026#34;: \u0026#34;search term\u0026#34; } } ] } } } Avoid expensive queries Bad: Wildcard queries\n{ \u0026#34;query\u0026#34;: { \u0026#34;wildcard\u0026#34;: { \u0026#34;title\u0026#34;: \u0026#34;*search*\u0026#34; // Very slow } } } Good: Use text search\n{ \u0026#34;query\u0026#34;: { \u0026#34;match\u0026#34;: { \u0026#34;title\u0026#34;: \u0026#34;search\u0026#34; } } } Limit result size { \u0026#34;size\u0026#34;: 20, // Limit results \u0026#34;from\u0026#34;: 0, \u0026#34;query\u0026#34;: { ... } } Use source filtering Only return needed fields:\n{ \u0026#34;_source\u0026#34;: [\u0026#34;title\u0026#34;, \u0026#34;created_at\u0026#34;], // Only return these fields \u0026#34;query\u0026#34;: { ... } } Cluster configuration JVM heap size Set to 50% of available RAM (max 32GB):\n# jvm.options -Xms16g -Xmx16g Why 50%?\nRemaining memory for OS cache Lucene uses off-heap memory Prevents swapping Thread pools Monitor and tune thread pools:\nGET /_nodes/thread_pool // Adjust if needed in elasticsearch.yml thread_pool: write: size: 4 queue_size: 200 search: size: 8 queue_size: 1000 Disk I/O optimization # Use SSD for data nodes # Disable swap bootstrap.memory_lock: true # Use multiple data paths path.data: [\u0026#34;/data1\u0026#34;, \u0026#34;/data2\u0026#34;, \u0026#34;/data3\u0026#34;] Monitoring and maintenance Key metrics Monitor these metrics:\nCluster health: GET /_cluster/health Node stats: GET /_nodes/stats Index stats: GET /_stats Pending tasks: GET /_cluster/pending_tasks Index lifecycle management Use ILM for automatic index management:\nPUT /_ilm/policy/my_policy { \u0026#34;policy\u0026#34;: { \u0026#34;phases\u0026#34;: { \u0026#34;hot\u0026#34;: { \u0026#34;actions\u0026#34;: { \u0026#34;rollover\u0026#34;: { \u0026#34;max_size\u0026#34;: \u0026#34;50GB\u0026#34;, \u0026#34;max_age\u0026#34;: \u0026#34;30d\u0026#34; } } }, \u0026#34;warm\u0026#34;: { \u0026#34;min_age\u0026#34;: \u0026#34;7d\u0026#34;, \u0026#34;actions\u0026#34;: { \u0026#34;shrink\u0026#34;: { \u0026#34;number_of_shards\u0026#34;: 1 }, \u0026#34;forcemerge\u0026#34;: { \u0026#34;max_num_segments\u0026#34;: 1 } } }, \u0026#34;delete\u0026#34;: { \u0026#34;min_age\u0026#34;: \u0026#34;90d\u0026#34;, \u0026#34;actions\u0026#34;: { \u0026#34;delete\u0026#34;: {} } } } } } Force merge Merge segments for better performance:\nPOST /my_index/_forcemerge?max_num_segments=1 When to use:\nAfter large data imports Before archiving When segments are too many Performance tuning checklist Indexing performance Use bulk API with optimal batch size Set refresh_interval appropriately Disable refresh during large imports Use async translog for better write performance Monitor indexing rate and adjust Query performance Use filters for exact matches Avoid wildcard queries Limit result size Use source filtering Cache frequently used filters Cluster configuration Set JVM heap to 50% of RAM (max 32GB) Configure node roles appropriately Set appropriate number of shards Use SSD for data nodes Disable swap (bootstrap.memory_lock) Monitoring Set up cluster health monitoring Monitor node stats regularly Track query performance Set up alerts for cluster issues Review slow query logs Common issues and solutions Too many shards Problem: Cluster has thousands of shards\nSolution:\nReduce shards per index Use index templates with ILM Consolidate small indices Hot spots Problem: Some nodes handle more load\nSolution:\nRebalance shards: POST /_cluster/reroute Check shard allocation Ensure even data distribution Slow queries Problem: Queries take too long\nSolution:\nReview query patterns Add appropriate indexes Use filters instead of queries Limit result size Profile queries: GET /_search?explain=true Conclusion Elasticsearch optimization requires understanding your data patterns, query requirements, and cluster architecture. Start with proper index design, optimize queries, and monitor cluster health regularly. Remember: Measure first, optimize based on data.\nContinuous monitoring and adjustment are key to maintaining optimal Elasticsearch performance in production.\n","permalink":"https://pixcave.com/posts/elasticsearch-cluster-optimization/","summary":"\u003cp\u003eElasticsearch is a powerful search and analytics engine, but optimizing it for production requires understanding indexing strategies, query patterns, and cluster configuration. This guide covers essential optimization techniques.\u003c/p\u003e\n\u003ch2 id=\"cluster-architecture\"\u003eCluster architecture\u003c/h2\u003e\n\u003ch3 id=\"node-roles\"\u003eNode roles\u003c/h3\u003e\n\u003cp\u003eConfigure nodes with specific roles:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Master node\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003enode.roles\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003emaster]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Data node\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003enode.roles\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003edata]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Ingest node\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003enode.roles\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003eingest]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Coordinating node (default)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003enode.roles\u003c/span\u003e: []  \u003cspan style=\"color:#75715e\"\u003e# No specific role\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"shard-strategy\"\u003eShard strategy\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003ePrimary shards\u003c/strong\u003e: Set at index creation (cannot be changed)\u003c/p\u003e","title":"Elasticsearch Cluster Optimization: Performance Tuning and Best Practices"},{"content":"Static (SAST) Run linters/semgrep/bandit/gosec/spotbugs per language; fail on high severity. Baseline to reduce noise; allow sarif upload to code host for inline review. Secret scanning in every push; block commits with keys. Dynamic (DAST) Stage environment with prod-like config; run zap/owasp/amass scopes carefully. Define allowlist targets; time-bounded scans; throttle to avoid DoS. Pipeline hygiene Shift-left: PR checks for fast SAST; nightly deeper scans. Artifacts stored with build SHA; track findings trend. Break-glass only with approvals; keep rules versioned. Checklist SAST/secret scans on push + PR. DAST on staging with scoped targets. SARIF/uploaded results visible to devs. Findings triaged with SLA. ","permalink":"https://pixcave.com/posts/security-sast-dast-pipeline/","summary":"\u003ch2 id=\"static-sast\"\u003eStatic (SAST)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRun linters/semgrep/bandit/gosec/spotbugs per language; fail on high severity.\u003c/li\u003e\n\u003cli\u003eBaseline to reduce noise; allow sarif upload to code host for inline review.\u003c/li\u003e\n\u003cli\u003eSecret scanning in every push; block commits with keys.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"dynamic-dast\"\u003eDynamic (DAST)\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eStage environment with prod-like config; run zap/owasp/amass scopes carefully.\u003c/li\u003e\n\u003cli\u003eDefine allowlist targets; time-bounded scans; throttle to avoid DoS.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"pipeline-hygiene\"\u003ePipeline hygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eShift-left: PR checks for fast SAST; nightly deeper scans.\u003c/li\u003e\n\u003cli\u003eArtifacts stored with build SHA; track findings trend.\u003c/li\u003e\n\u003cli\u003eBreak-glass only with approvals; keep rules versioned.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e SAST/secret scans on push + PR.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e DAST on staging with scoped targets.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e SARIF/uploaded results visible to devs.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Findings triaged with SLA.\u003c/li\u003e\n\u003c/ul\u003e","title":"SAST + DAST in CI: Quick Wins"},{"content":"Choosing engine Redis: rich data types, persistence, clustering, scripts; good for queues/rate limits. Memcached: simple KV, pure in-memory, fast; great for stateless caches. Design Namespaced keys, versioned; TTL with jitter; avoid giant values. Pick eviction (LRU/LFU); monitor hit rate and evictions. Stampede control: locks/SETNX, stale-while-revalidate, per-key backoff. Ops Pooling + timeouts; alert on latency, evictions, memory fragmentation. For Redis, persistence config (AOF/RDB) matched to durability needs; replicas for HA. For Memcached, spread slabs; watch for evictions of hot slabs. Checklist Engine chosen per use case; durability/HA decided. TTLs + jitter; stampede protection in place. Metrics for hit/miss/evictions/latency. ","permalink":"https://pixcave.com/posts/cache-tier-design-redis-vs-memcached/","summary":"\u003ch2 id=\"choosing-engine\"\u003eChoosing engine\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRedis: rich data types, persistence, clustering, scripts; good for queues/rate limits.\u003c/li\u003e\n\u003cli\u003eMemcached: simple KV, pure in-memory, fast; great for stateless caches.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"design\"\u003eDesign\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eNamespaced keys, versioned; TTL with jitter; avoid giant values.\u003c/li\u003e\n\u003cli\u003ePick eviction (LRU/LFU); monitor hit rate and evictions.\u003c/li\u003e\n\u003cli\u003eStampede control: locks/SETNX, stale-while-revalidate, per-key backoff.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ops\"\u003eOps\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePooling + timeouts; alert on latency, evictions, memory fragmentation.\u003c/li\u003e\n\u003cli\u003eFor Redis, persistence config (AOF/RDB) matched to durability needs; replicas for HA.\u003c/li\u003e\n\u003cli\u003eFor Memcached, spread slabs; watch for evictions of hot slabs.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Engine chosen per use case; durability/HA decided.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e TTLs + jitter; stampede protection in place.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics for hit/miss/evictions/latency.\u003c/li\u003e\n\u003c/ul\u003e","title":"Cache Tier Design: Redis vs Memcached"},{"content":"Security is crucial in web development. Here are essential security practices to protect your applications.\n1. Authentication \u0026amp; Authorization Strong Password Policies // Enforce strong passwords const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?\u0026amp;])[A-Za-z\\d@$!%*?\u0026amp;]{8,}$/; // Hash passwords (never store plaintext) const hashedPassword = await bcrypt.hash(password, 10); JWT Best Practices // Use short expiration times const token = jwt.sign( { userId: user.id }, process.env.JWT_SECRET, { expiresIn: \u0026#39;15m\u0026#39; } ); // Implement refresh tokens // Store tokens securely (httpOnly cookies) 2. Input Validation Server-Side Validation // Always validate on server const schema = z.object({ email: z.string().email(), password: z.string().min(8), age: z.number().min(18).max(120) }); const validated = schema.parse(req.body); Sanitize Inputs // Prevent XSS const sanitized = DOMPurify.sanitize(userInput); // Prevent SQL Injection (use parameterized queries) db.query(\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;, [userId]); 3. HTTPS \u0026amp; SSL/TLS // Always use HTTPS in production // Redirect HTTP to HTTPS // Use HSTS headers app.use((req, res, next) =\u0026gt; { if (!req.secure \u0026amp;\u0026amp; process.env.NODE_ENV === \u0026#39;production\u0026#39;) { return res.redirect(`https://${req.headers.host}${req.url}`); } next(); }); 4. CORS Configuration // Configure CORS properly app.use(cors({ origin: process.env.ALLOWED_ORIGINS.split(\u0026#39;,\u0026#39;), credentials: true, methods: [\u0026#39;GET\u0026#39;, \u0026#39;POST\u0026#39;, \u0026#39;PUT\u0026#39;, \u0026#39;DELETE\u0026#39;], allowedHeaders: [\u0026#39;Content-Type\u0026#39;, \u0026#39;Authorization\u0026#39;] })); 5. Rate Limiting // Prevent brute force attacks const rateLimit = require(\u0026#39;express-rate-limit\u0026#39;); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 5 // limit each IP to 5 requests per windowMs }); app.use(\u0026#39;/api/login\u0026#39;, limiter); 6. SQL Injection Prevention // Always use parameterized queries // Bad db.query(`SELECT * FROM users WHERE email = \u0026#39;${email}\u0026#39;`); // Good db.query(\u0026#39;SELECT * FROM users WHERE email = ?\u0026#39;, [email]); 7. XSS Prevention // Escape user input const escapeHtml = (text) =\u0026gt; { const map = { \u0026#39;\u0026amp;\u0026#39;: \u0026#39;\u0026amp;amp;\u0026#39;, \u0026#39;\u0026lt;\u0026#39;: \u0026#39;\u0026amp;lt;\u0026#39;, \u0026#39;\u0026gt;\u0026#39;: \u0026#39;\u0026amp;gt;\u0026#39;, \u0026#39;\u0026#34;\u0026#39;: \u0026#39;\u0026amp;quot;\u0026#39;, \u0026#34;\u0026#39;\u0026#34;: \u0026#39;\u0026amp;#039;\u0026#39; }; return text.replace(/[\u0026amp;\u0026lt;\u0026gt;\u0026#34;\u0026#39;]/g, m =\u0026gt; map[m]); }; // Use Content Security Policy app.use((req, res, next) =\u0026gt; { res.setHeader(\u0026#39;Content-Security-Policy\u0026#39;, \u0026#34;default-src \u0026#39;self\u0026#39;; script-src \u0026#39;self\u0026#39;\u0026#34;); next(); }); 8. CSRF Protection // Use CSRF tokens const csrf = require(\u0026#39;csurf\u0026#39;); const csrfProtection = csrf({ cookie: true }); app.use(csrfProtection); app.get(\u0026#39;/form\u0026#39;, (req, res) =\u0026gt; { res.render(\u0026#39;form\u0026#39;, { csrfToken: req.csrfToken() }); }); 9. Security Headers // Set security headers app.use((req, res, next) =\u0026gt; { res.setHeader(\u0026#39;X-Content-Type-Options\u0026#39;, \u0026#39;nosniff\u0026#39;); res.setHeader(\u0026#39;X-Frame-Options\u0026#39;, \u0026#39;DENY\u0026#39;); res.setHeader(\u0026#39;X-XSS-Protection\u0026#39;, \u0026#39;1; mode=block\u0026#39;); res.setHeader(\u0026#39;Strict-Transport-Security\u0026#39;, \u0026#39;max-age=31536000\u0026#39;); next(); }); 10. Dependency Security # Regularly update dependencies npm audit npm audit fix # Use tools like Snyk, Dependabot 11. Error Handling // Don\u0026#39;t expose sensitive information app.use((err, req, res, next) =\u0026gt; { if (process.env.NODE_ENV === \u0026#39;production\u0026#39;) { res.status(500).json({ error: \u0026#39;Internal server error\u0026#39; }); } else { res.status(500).json({ error: err.message }); } }); 12. Logging \u0026amp; Monitoring // Log security events logger.warn(\u0026#39;Failed login attempt\u0026#39;, { ip: req.ip, email: req.body.email, timestamp: new Date() }); // Monitor for suspicious activity Best Practices Summary Strong authentication Input validation \u0026amp; sanitization Use HTTPS Configure CORS properly Implement rate limiting Prevent SQL injection Prevent XSS CSRF protection Security headers Keep dependencies updated Proper error handling Monitor security events Conclusion Security requires:\nDefense in depth Regular updates Security audits Team training Incident response plan Security is not optional—it\u0026rsquo;s essential! 🔒\n","permalink":"https://pixcave.com/posts/security-best-practices-web-development/","summary":"\u003cp\u003eSecurity is crucial in web development. Here are essential security practices to protect your applications.\u003c/p\u003e\n\u003ch2 id=\"1-authentication--authorization\"\u003e1. Authentication \u0026amp; Authorization\u003c/h2\u003e\n\u003ch3 id=\"strong-password-policies\"\u003eStrong Password Policies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Enforce strong passwords\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epasswordRegex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?\u0026amp;])[A-Za-z\\d@$!%*?\u0026amp;]{8,}$/\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Hash passwords (never store plaintext)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehashedPassword\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebcrypt\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehash\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"jwt-best-practices\"\u003eJWT Best Practices\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use short expiration times\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etoken\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejwt\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esign\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  { \u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eJWT_SECRET\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  { \u003cspan style=\"color:#a6e22e\"\u003eexpiresIn\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;15m\u0026#39;\u003c/span\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Implement refresh tokens\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Store tokens securely (httpOnly cookies)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-input-validation\"\u003e2. Input Validation\u003c/h2\u003e\n\u003ch3 id=\"server-side-validation\"\u003eServer-Side Validation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always validate on server\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eschema\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ez\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eobject\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ez\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estring\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e(),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ez\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estring\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003emin\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eage\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ez\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003enumber\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003emin\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e18\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003emax\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e120\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalidated\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eschema\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eparse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"sanitize-inputs\"\u003eSanitize Inputs\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Prevent XSS\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esanitized\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDOMPurify\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esanitize\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserInput\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Prevent SQL Injection (use parameterized queries)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003euserId\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-https--ssltls\"\u003e3. HTTPS \u0026amp; SSL/TLS\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always use HTTPS in production\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Redirect HTTP to HTTPS\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use HSTS headers\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esecure\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eNODE_ENV\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;production\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eredirect\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`https://\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheaders\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehost\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eurl\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-cors-configuration\"\u003e4. CORS Configuration\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Configure CORS properly\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecors\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eorigin\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eALLOWED_ORIGINS\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esplit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;,\u0026#39;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecredentials\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emethods\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GET\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;POST\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;PUT\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;DELETE\u0026#39;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eallowedHeaders\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Content-Type\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Authorization\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-rate-limiting\"\u003e5. Rate Limiting\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Prevent brute force attacks\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erateLimit\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;express-rate-limit\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elimiter\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erateLimit\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewindowMs\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e, \u003cspan style=\"color:#75715e\"\u003e// 15 minutes\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003emax\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// limit each IP to 5 requests per windowMs\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/login\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003elimiter\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-sql-injection-prevention\"\u003e6. SQL Injection Prevention\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Always use parameterized queries\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`SELECT * FROM users WHERE email = \u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SELECT * FROM users WHERE email = ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-xss-prevention\"\u003e7. XSS Prevention\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Escape user input\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eescapeHtml\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003etext\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;amp;\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026lt;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;lt;\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026gt;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;gt;\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#34;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;quot;\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#39;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;#039;\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etext\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereplace\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e/[\u0026amp;\u0026lt;\u0026gt;\u0026#34;\u0026#39;]/g\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003em\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use Content Security Policy\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetHeader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Content-Security-Policy\u0026#39;\u003c/span\u003e, \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;default-src \u0026#39;self\u0026#39;; script-src \u0026#39;self\u0026#39;\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"8-csrf-protection\"\u003e8. CSRF Protection\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use CSRF tokens\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecsrf\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;csurf\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecsrfProtection\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecsrf\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ecookie\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecsrfProtection\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/form\u0026#39;\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;form\u0026#39;\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003ecsrfToken\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecsrfToken\u003c/span\u003e() });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"9-security-headers\"\u003e9. Security Headers\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Set security headers\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetHeader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;X-Content-Type-Options\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;nosniff\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetHeader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;X-Frame-Options\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;DENY\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetHeader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;X-XSS-Protection\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;1; mode=block\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetHeader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Strict-Transport-Security\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;max-age=31536000\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"10-dependency-security\"\u003e10. Dependency Security\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Regularly update dependencies\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm audit\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm audit fix\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Use tools like Snyk, Dependabot\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"11-error-handling\"\u003e11. Error Handling\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Don\u0026#39;t expose sensitive information\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euse\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enext\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eNODE_ENV\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;production\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e500\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ejson\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Internal server error\u0026#39;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eres\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e500\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ejson\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eerr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"12-logging--monitoring\"\u003e12. Logging \u0026amp; Monitoring\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Log security events\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003elogger\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewarn\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Failed login attempt\u0026#39;\u003c/span\u003e, {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereq\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003etimestamp\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Date()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Monitor for suspicious activity\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices-summary\"\u003eBest Practices Summary\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eStrong authentication\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInput validation \u0026amp; sanitization\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse HTTPS\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfigure CORS properly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement rate limiting\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePrevent SQL injection\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePrevent XSS\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCSRF protection\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSecurity headers\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKeep dependencies updated\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProper error handling\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor security events\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSecurity requires:\u003c/p\u003e","title":"Web Security Best Practices: Protecting Your Applications"},{"content":"Kubernetes provides several deployment strategies to ensure zero-downtime updates and safe rollouts of new application versions. Understanding these strategies is crucial for maintaining reliable production systems.\nDeployment strategy overview Kubernetes deployment strategies determine how new versions of your application replace old ones. The choice depends on:\nRisk tolerance: How critical is zero downtime? Traffic patterns: Can you route traffic to multiple versions? Rollback speed: How quickly can you revert if issues occur? Resource constraints: Can you run multiple versions simultaneously? Rolling update (default) The default Kubernetes deployment strategy gradually replaces old pods with new ones.\nHow it works Creates new pods with the new version Terminates old pods as new ones become ready Maintains service availability throughout the process Configuration apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 5 strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 # Can have 2 extra pods during update maxUnavailable: 1 # Max 1 pod unavailable at a time template: spec: containers: - name: app image: myapp:v2 Advantages Zero downtime (when configured correctly) Resource efficient (no need for double capacity) Built into Kubernetes (no additional tools needed) Disadvantages Brief period with mixed versions Rollback takes time (must wait for pods to terminate) Potential for cascading failures if new version has issues Blue-green deployment Run two identical production environments: blue (current) and green (new version). Switch traffic instantly between them.\nImplementation # Blue deployment (current version) apiVersion: apps/v1 kind: Deployment metadata: name: myapp-blue spec: replicas: 5 template: metadata: labels: app: myapp version: blue spec: containers: - name: app image: myapp:v1 --- # Green deployment (new version) apiVersion: apps/v1 kind: Deployment metadata: name: myapp-green spec: replicas: 5 template: metadata: labels: app: myapp version: green spec: containers: - name: app image: myapp:v2 --- # Service selector (switch between blue/green) apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: myapp version: blue # Change to \u0026#39;green\u0026#39; to switch ports: - port: 80 targetPort: 8080 Switching traffic # Switch to green kubectl patch service myapp-service -p \u0026#39;{\u0026#34;spec\u0026#34;:{\u0026#34;selector\u0026#34;:{\u0026#34;version\u0026#34;:\u0026#34;green\u0026#34;}}}\u0026#39; # Rollback to blue kubectl patch service myapp-service -p \u0026#39;{\u0026#34;spec\u0026#34;:{\u0026#34;selector\u0026#34;:{\u0026#34;version\u0026#34;:\u0026#34;blue\u0026#34;}}}\u0026#39; Advantages Instant rollback (just switch service selector) No mixed versions during transition Easy to test new version before switching Disadvantages Requires double resources during deployment Database migrations can be complex More complex setup and management Canary deployment Gradually roll out new version to a small percentage of users, then increase if successful.\nImplementation with Istio apiVersion: apps/v1 kind: Deployment metadata: name: myapp-v1 spec: replicas: 9 template: metadata: labels: app: myapp version: v1 spec: containers: - name: app image: myapp:v1 --- apiVersion: apps/v1 kind: Deployment metadata: name: myapp-v2 spec: replicas: 1 # 10% of traffic template: metadata: labels: app: myapp version: v2 spec: containers: - name: app image: myapp:v2 --- # Istio VirtualService for traffic splitting apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: myapp spec: hosts: - myapp http: - match: - headers: canary: exact: \u0026#34;true\u0026#34; route: - destination: host: myapp subset: v2 weight: 100 - route: - destination: host: myapp subset: v1 weight: 90 - destination: host: myapp subset: v2 weight: 10 Native Kubernetes canary # Canary deployment (10% traffic) apiVersion: apps/v1 kind: Deployment metadata: name: myapp-canary spec: replicas: 1 template: metadata: labels: app: myapp track: canary spec: containers: - name: app image: myapp:v2 --- # Service with both stable and canary apiVersion: v1 kind: Service metadata: name: myapp spec: selector: app: myapp ports: - port: 80 Advantages Low risk (only small percentage of users affected) Real-world testing with production traffic Gradual rollout reduces blast radius Disadvantages Requires traffic splitting mechanism (Istio, service mesh, or ingress controller) More complex monitoring (need to track both versions) Longer deployment process A/B testing deployment Similar to canary but based on user characteristics rather than percentage.\nImplementation # Use Istio or similar for header-based routing apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: myapp spec: hosts: - myapp http: - match: - headers: user-segment: exact: \u0026#34;beta\u0026#34; route: - destination: host: myapp subset: v2 - route: - destination: host: myapp subset: v1 Choosing the right strategy Use rolling update when: Application is stateless or handles version mixing well Resource constraints are a concern Simple rollback is acceptable Use blue-green when: Zero downtime is critical Instant rollback is required You have sufficient resources Database migrations are straightforward Use canary when: You want to test with real production traffic Risk mitigation is important You have monitoring and alerting in place Gradual rollout is preferred Best practices 1. Health checks Always configure proper health checks:\nspec: containers: - name: app livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 2. Resource limits Set resource requests and limits:\nresources: requests: memory: \u0026#34;256Mi\u0026#34; cpu: \u0026#34;250m\u0026#34; limits: memory: \u0026#34;512Mi\u0026#34; cpu: \u0026#34;500m\u0026#34; 3. Pod disruption budgets Protect against voluntary disruptions:\napiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: myapp-pdb spec: minAvailable: 3 selector: matchLabels: app: myapp 4. Monitoring and alerting Monitor key metrics during deployments:\nError rates Response times Resource usage Custom business metrics 5. Automated rollback Set up automated rollback on failure:\nspec: progressDeadlineSeconds: 600 # Rollback if not progressing revisionHistoryLimit: 10 # Keep old revisions for rollback Conclusion Choosing the right Kubernetes deployment strategy depends on your application\u0026rsquo;s requirements, risk tolerance, and infrastructure capabilities. Start with rolling updates for simplicity, then move to blue-green or canary deployments as your needs become more sophisticated.\nRemember: Test your deployment strategy in staging first, and always have a rollback plan ready.\n","permalink":"https://pixcave.com/posts/kubernetes-deployment-strategies-2024/","summary":"\u003cp\u003eKubernetes provides several deployment strategies to ensure zero-downtime updates and safe rollouts of new application versions. Understanding these strategies is crucial for maintaining reliable production systems.\u003c/p\u003e\n\u003ch2 id=\"deployment-strategy-overview\"\u003eDeployment strategy overview\u003c/h2\u003e\n\u003cp\u003eKubernetes deployment strategies determine how new versions of your application replace old ones. The choice depends on:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRisk tolerance\u003c/strong\u003e: How critical is zero downtime?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTraffic patterns\u003c/strong\u003e: Can you route traffic to multiple versions?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRollback speed\u003c/strong\u003e: How quickly can you revert if issues occur?\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eResource constraints\u003c/strong\u003e: Can you run multiple versions simultaneously?\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"rolling-update-default\"\u003eRolling update (default)\u003c/h2\u003e\n\u003cp\u003eThe default Kubernetes deployment strategy gradually replaces old pods with new ones.\u003c/p\u003e","title":"Kubernetes Deployment Strategies: Rolling Updates, Blue-Green, and Canary"},{"content":"Low-effort wins php artisan config:cache, route:cache, view:cache; warm on deploy. Enable OPcache with sane limits; preloading for hot classes when applicable. Use queues for emails/webhooks; keep HTTP requests lean. Database hygiene Add missing indexes; avoid N+1 with eager loading; paginate large lists. Use read replicas where safe; cap per-request query count in logs. Measure slow queries; set alarms on p95 query time. HTTP layer Cache responses with tags (Redis) for fast invalidation. Use CDN for static/media; compress and set cache headers. Leverage middleware to short-circuit authenticated user cache when possible. Observability Laravel Telescope or Horizon for queues; metrics on throughput, failures, latency. Log DB/query counts; track opcache hit rate and memory usage. Checklist Config/route/view cached on deploy. OPcache enabled and monitored. DB queries optimized and indexed; N+1 checks in CI. Responses cached where safe; queues handle slow work. ","permalink":"https://pixcave.com/posts/php-laravel-performance-caching-2024/","summary":"\u003ch2 id=\"low-effort-wins\"\u003eLow-effort wins\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003ephp artisan config:cache\u003c/code\u003e, \u003ccode\u003eroute:cache\u003c/code\u003e, \u003ccode\u003eview:cache\u003c/code\u003e; warm on deploy.\u003c/li\u003e\n\u003cli\u003eEnable OPcache with sane limits; preloading for hot classes when applicable.\u003c/li\u003e\n\u003cli\u003eUse queues for emails/webhooks; keep HTTP requests lean.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"database-hygiene\"\u003eDatabase hygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAdd missing indexes; avoid N+1 with eager loading; paginate large lists.\u003c/li\u003e\n\u003cli\u003eUse read replicas where safe; cap per-request query count in logs.\u003c/li\u003e\n\u003cli\u003eMeasure slow queries; set alarms on p95 query time.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"http-layer\"\u003eHTTP layer\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eCache responses with tags (Redis) for fast invalidation.\u003c/li\u003e\n\u003cli\u003eUse CDN for static/media; compress and set cache headers.\u003c/li\u003e\n\u003cli\u003eLeverage middleware to short-circuit authenticated user cache when possible.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLaravel Telescope or Horizon for queues; metrics on throughput, failures, latency.\u003c/li\u003e\n\u003cli\u003eLog DB/query counts; track opcache hit rate and memory usage.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Config/route/view cached on deploy.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e OPcache enabled and monitored.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e DB queries optimized and indexed; N+1 checks in CI.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Responses cached where safe; queues handle slow work.\u003c/li\u003e\n\u003c/ul\u003e","title":"Laravel Performance \u0026 Caching Playbook (2024)"},{"content":"Keys \u0026amp; TTLs Namespaced keys: app:domain:entity:id. Set TTLs per data volatility; use jitter to avoid thundering expirations. Version keys on schema changes to prevent stale reads. Stampede protection Use SETNX/lock around rebuild; short lock TTL with fallback. Serve stale-while-revalidate: return cached value, refresh asynchronously. Serialization \u0026amp; size Prefer JSON with bounded fields; compress only large blobs. Avoid massive lists/hashes; paginate or split keys. Operations Monitor hit rate, command latency, memory, evictions. Use connection pooling; set timeouts and retries with backoff. Cluster/replica for HA; read from replicas if consistency allows. Checklist Keys versioned; TTLs with jitter. Stampede controls in place. Metrics for hit/miss/latency/evictions; alerts configured. ","permalink":"https://pixcave.com/posts/node-redis-caching-patterns/","summary":"\u003ch2 id=\"keys--ttls\"\u003eKeys \u0026amp; TTLs\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eNamespaced keys: \u003ccode\u003eapp:domain:entity:id\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSet TTLs per data volatility; use jitter to avoid thundering expirations.\u003c/li\u003e\n\u003cli\u003eVersion keys on schema changes to prevent stale reads.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"stampede-protection\"\u003eStampede protection\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse \u003ccode\u003eSETNX\u003c/code\u003e/lock around rebuild; short lock TTL with fallback.\u003c/li\u003e\n\u003cli\u003eServe stale-while-revalidate: return cached value, refresh asynchronously.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"serialization--size\"\u003eSerialization \u0026amp; size\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePrefer JSON with bounded fields; compress only large blobs.\u003c/li\u003e\n\u003cli\u003eAvoid massive lists/hashes; paginate or split keys.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"operations\"\u003eOperations\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMonitor hit rate, command latency, memory, evictions.\u003c/li\u003e\n\u003cli\u003eUse connection pooling; set timeouts and retries with backoff.\u003c/li\u003e\n\u003cli\u003eCluster/replica for HA; read from replicas if consistency allows.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Keys versioned; TTLs with jitter.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Stampede controls in place.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metrics for hit/miss/latency/evictions; alerts configured.\u003c/li\u003e\n\u003c/ul\u003e","title":"Node.js Redis Caching Patterns"},{"content":"Query hygiene Add composite indexes matching filters/order; avoid leading wildcards. Use EXPLAIN to verify index usage; watch for filesort/temp tables. Prefer keyset pagination over OFFSET for large tables. Config basics Set innodb_buffer_pool_size (50-70% RAM), innodb_log_file_size, innodb_flush_log_at_trx_commit=1 (durable) or 2 (faster). max_connections aligned with app pool size; avoid connection storms. Enable slow query log with sane threshold; sample for tuning. App considerations Reuse connections (pooling); avoid long transactions. Limit selected columns; cap payload sizes; avoid large unbounded IN lists. For read-heavy workloads, add replicas; route reads carefully. Checklist Indexes audited; EXPLAIN reviewed. Buffer pool sized; slow log enabled. Pagination and payloads bounded; connections pooled. ","permalink":"https://pixcave.com/posts/php-mysql-optimizer-checklist/","summary":"\u003ch2 id=\"query-hygiene\"\u003eQuery hygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAdd composite indexes matching filters/order; avoid leading wildcards.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003eEXPLAIN\u003c/code\u003e to verify index usage; watch for filesort/temp tables.\u003c/li\u003e\n\u003cli\u003ePrefer keyset pagination over \u003ccode\u003eOFFSET\u003c/code\u003e for large tables.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"config-basics\"\u003eConfig basics\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet \u003ccode\u003einnodb_buffer_pool_size\u003c/code\u003e (50-70% RAM), \u003ccode\u003einnodb_log_file_size\u003c/code\u003e, \u003ccode\u003einnodb_flush_log_at_trx_commit=1\u003c/code\u003e (durable) or 2 (faster).\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emax_connections\u003c/code\u003e aligned with app pool size; avoid connection storms.\u003c/li\u003e\n\u003cli\u003eEnable slow query log with sane threshold; sample for tuning.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"app-considerations\"\u003eApp considerations\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eReuse connections (pooling); avoid long transactions.\u003c/li\u003e\n\u003cli\u003eLimit selected columns; cap payload sizes; avoid large unbounded \u003ccode\u003eIN\u003c/code\u003e lists.\u003c/li\u003e\n\u003cli\u003eFor read-heavy workloads, add replicas; route reads carefully.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Indexes audited; EXPLAIN reviewed.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Buffer pool sized; slow log enabled.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Pagination and payloads bounded; connections pooled.\u003c/li\u003e\n\u003c/ul\u003e","title":"MySQL Optimizer Checklist for PHP Apps"},{"content":"Comprehensive testing is essential for reliable backend systems. Here\u0026rsquo;s a guide to effective testing strategies.\nTesting Pyramid /\\ / \\ E2E Tests (Few) /____\\ / \\ Integration Tests (Some) /________\\ / \\ Unit Tests (Many) /____________\\ 1. Unit Tests What to Test Individual functions Business logic Data transformations Edge cases Example describe(\u0026#39;UserService\u0026#39;, () =\u0026gt; { it(\u0026#39;should create user with valid data\u0026#39;, () =\u0026gt; { const userData = { email: \u0026#39;test@example.com\u0026#39;, name: \u0026#39;Test User\u0026#39; }; const user = userService.createUser(userData); expect(user.email).toBe(\u0026#39;test@example.com\u0026#39;); expect(user.id).toBeDefined(); }); it(\u0026#39;should throw error for duplicate email\u0026#39;, () =\u0026gt; { userService.createUser({ email: \u0026#39;test@example.com\u0026#39; }); expect(() =\u0026gt; { userService.createUser({ email: \u0026#39;test@example.com\u0026#39; }); }).toThrow(\u0026#39;Email already exists\u0026#39;); }); }); 2. Integration Tests What to Test API endpoints Database operations External service interactions Service integration Example describe(\u0026#39;User API\u0026#39;, () =\u0026gt; { beforeEach(async () =\u0026gt; { await db.migrate.latest(); }); afterEach(async () =\u0026gt; { await db.migrate.rollback(); }); it(\u0026#39;POST /api/users should create user\u0026#39;, async () =\u0026gt; { const response = await request(app) .post(\u0026#39;/api/users\u0026#39;) .send({ email: \u0026#39;test@example.com\u0026#39;, name: \u0026#39;Test User\u0026#39;, password: \u0026#39;password123\u0026#39; }) .expect(201); expect(response.body.email).toBe(\u0026#39;test@example.com\u0026#39;); const user = await db(\u0026#39;users\u0026#39;).where({ email: \u0026#39;test@example.com\u0026#39; }).first(); expect(user).toBeDefined(); }); }); 3. End-to-End Tests What to Test Complete user workflows System integration Critical paths Example describe(\u0026#39;User Registration Flow\u0026#39;, () =\u0026gt; { it(\u0026#39;should complete full registration process\u0026#39;, async () =\u0026gt; { // Register user const registerResponse = await request(app) .post(\u0026#39;/api/auth/register\u0026#39;) .send({ email: \u0026#39;test@example.com\u0026#39;, password: \u0026#39;password123\u0026#39; }); expect(registerResponse.status).toBe(201); // Login const loginResponse = await request(app) .post(\u0026#39;/api/auth/login\u0026#39;) .send({ email: \u0026#39;test@example.com\u0026#39;, password: \u0026#39;password123\u0026#39; }); expect(loginResponse.status).toBe(200); expect(loginResponse.body.token).toBeDefined(); // Access protected route const profileResponse = await request(app) .get(\u0026#39;/api/users/me\u0026#39;) .set(\u0026#39;Authorization\u0026#39;, `Bearer ${loginResponse.body.token}`); expect(profileResponse.status).toBe(200); }); }); 4. Test Data Management Fixtures const userFixtures = { validUser: { email: \u0026#39;test@example.com\u0026#39;, name: \u0026#39;Test User\u0026#39;, password: \u0026#39;password123\u0026#39; }, adminUser: { email: \u0026#39;admin@example.com\u0026#39;, name: \u0026#39;Admin\u0026#39;, password: \u0026#39;admin123\u0026#39;, role: \u0026#39;admin\u0026#39; } }; Factories function createUser(overrides = {}) { return { email: \u0026#39;test@example.com\u0026#39;, name: \u0026#39;Test User\u0026#39;, password: \u0026#39;password123\u0026#39;, ...overrides }; } 5. Mocking External Services // Mock external API jest.mock(\u0026#39;../services/paymentService\u0026#39;, () =\u0026gt; ({ processPayment: jest.fn().mockResolvedValue({ transactionId: \u0026#39;tx_123\u0026#39;, status: \u0026#39;success\u0026#39; }) })); 6. Database Testing // Use test database const testDb = { host: process.env.TEST_DB_HOST, database: process.env.TEST_DB_NAME }; // Clean database between tests beforeEach(async () =\u0026gt; { await db.raw(\u0026#39;TRUNCATE TABLE users CASCADE\u0026#39;); }); 7. Test Coverage // Aim for high coverage // Focus on critical paths // Don\u0026#39;t obsess over 100% // Use coverage tools // jest --coverage // nyc Best Practices Write tests first (TDD) Test behavior, not implementation Keep tests independent Use descriptive test names Test edge cases Mock external dependencies Clean up test data Run tests in CI/CD Maintain test code quality Review test failures Conclusion Effective testing requires:\nRight test types for the situation Good test organization Proper mocking CI/CD integration Regular maintenance Test thoroughly, ship confidently! 🧪\n","permalink":"https://pixcave.com/posts/testing-strategies-backend/","summary":"\u003cp\u003eComprehensive testing is essential for reliable backend systems. Here\u0026rsquo;s a guide to effective testing strategies.\u003c/p\u003e\n\u003ch2 id=\"testing-pyramid\"\u003eTesting Pyramid\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        /\\\n       /  \\      E2E Tests (Few)\n      /____\\\n     /      \\    Integration Tests (Some)\n    /________\\\n   /          \\  Unit Tests (Many)\n  /____________\\\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"1-unit-tests\"\u003e1. Unit Tests\u003c/h2\u003e\n\u003ch3 id=\"what-to-test\"\u003eWhat to Test\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eIndividual functions\u003c/li\u003e\n\u003cli\u003eBusiness logic\u003c/li\u003e\n\u003cli\u003eData transformations\u003c/li\u003e\n\u003cli\u003eEdge cases\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"example\"\u003eExample\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edescribe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;UserService\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;should create user with valid data\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euserData\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Test User\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euserService\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euserData\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBeDefined\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;should throw error for duplicate email\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003euserService\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003euserService\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }).\u003cspan style=\"color:#a6e22e\"\u003etoThrow\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Email already exists\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-integration-tests\"\u003e2. Integration Tests\u003c/h2\u003e\n\u003ch3 id=\"what-to-test-1\"\u003eWhat to Test\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAPI endpoints\u003c/li\u003e\n\u003cli\u003eDatabase operations\u003c/li\u003e\n\u003cli\u003eExternal service interactions\u003c/li\u003e\n\u003cli\u003eService integration\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"example-1\"\u003eExample\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edescribe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;User API\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ebeforeEach\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emigrate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elatest\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eafterEach\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emigrate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003erollback\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;POST /api/users should create user\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresponse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003epost\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/users\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Test User\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e201\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ewhere\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e }).\u003cspan style=\"color:#a6e22e\"\u003efirst\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBeDefined\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-end-to-end-tests\"\u003e3. End-to-End Tests\u003c/h2\u003e\n\u003ch3 id=\"what-to-test-2\"\u003eWhat to Test\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eComplete user workflows\u003c/li\u003e\n\u003cli\u003eSystem integration\u003c/li\u003e\n\u003cli\u003eCritical paths\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"example-2\"\u003eExample\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edescribe\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;User Registration Flow\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;should complete full registration process\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Register user\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eregisterResponse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003epost\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/auth/register\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eregisterResponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBe\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e201\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Login\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eloginResponse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003epost\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/auth/login\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eloginResponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBe\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eloginResponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etoken\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBeDefined\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Access protected route\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprofileResponse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/api/users/me\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      .\u003cspan style=\"color:#a6e22e\"\u003eset\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Authorization\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e`Bearer \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eloginResponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etoken\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eexpect\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eprofileResponse\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003etoBe\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-test-data-management\"\u003e4. Test Data Management\u003c/h2\u003e\n\u003ch3 id=\"fixtures\"\u003eFixtures\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euserFixtures\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003evalidUser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Test User\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eadminUser\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;admin@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Admin\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;admin123\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erole\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;admin\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"factories\"\u003eFactories\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eoverrides\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {}) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Test User\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003epassword\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;password123\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ...\u003cspan style=\"color:#a6e22e\"\u003eoverrides\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-mocking-external-services\"\u003e5. Mocking External Services\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Mock external API\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ejest\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emock\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;../services/paymentService\u0026#39;\u003c/span\u003e, () =\u0026gt; ({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eprocessPayment\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejest\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efn\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003emockResolvedValue\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003etransactionId\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tx_123\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;success\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-database-testing\"\u003e6. Database Testing\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use test database\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etestDb\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ehost\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eTEST_DB_HOST\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edatabase\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eTEST_DB_NAME\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Clean database between tests\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ebeforeEach\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eraw\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;TRUNCATE TABLE users CASCADE\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-test-coverage\"\u003e7. Test Coverage\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Aim for high coverage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Focus on critical paths\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Don\u0026#39;t obsess over 100%\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Use coverage tools\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// jest --coverage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// nyc\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eWrite tests first\u003c/strong\u003e (TDD)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest behavior, not implementation\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKeep tests independent\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse descriptive test names\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest edge cases\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMock external dependencies\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eClean up test data\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRun tests in CI/CD\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMaintain test code quality\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReview test failures\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eEffective testing requires:\u003c/p\u003e","title":"Backend Testing Strategies: Unit, Integration, and E2E Tests"},{"content":"Pooling Use a pool (pg/pgbouncer); size = (CPU * 2–4) per app instance; avoid per-request connections. For PgBouncer in transaction mode, avoid session features (temp tables, session prep statements). Query hygiene Parameterize queries; prevent plan cache thrash; set statement timeout. Add indexes; avoid wild % patterns; paginate with keyset when possible. Monitor slow queries; cap max rows returned; avoid huge JSON blobs. App settings Set statement_timeout, idle_in_transaction_session_timeout. Use prepared statements judiciously; for PgBouncer, prefer server-prepared off or use pgbouncer session mode. Pool instrumentation: queue wait time, checkout latency, timeouts. OS/DB basics Keep Postgres on same AZ/region; latency kills. Tune work_mem, shared_buffers, effective_cache_size appropriately (DB side). Use EXPLAIN (ANALYZE, BUFFERS) in staging for heavy queries. Checklist Pool sized and monitored; PgBouncer for many short connections. Query timeouts set; slow logs monitored. Key indexes present; pagination optimized. App-level metrics for pool wait, query latency, error rates. ","permalink":"https://pixcave.com/posts/node-postgres-performance-2024/","summary":"\u003ch2 id=\"pooling\"\u003ePooling\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUse a pool (pg/pgbouncer); size = (CPU * 2–4) per app instance; avoid per-request connections.\u003c/li\u003e\n\u003cli\u003eFor PgBouncer in transaction mode, avoid session features (temp tables, session prep statements).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"query-hygiene\"\u003eQuery hygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eParameterize queries; prevent plan cache thrash; set statement timeout.\u003c/li\u003e\n\u003cli\u003eAdd indexes; avoid wild \u003ccode\u003e%\u003c/code\u003e patterns; paginate with keyset when possible.\u003c/li\u003e\n\u003cli\u003eMonitor slow queries; cap max rows returned; avoid huge JSON blobs.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"app-settings\"\u003eApp settings\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet \u003ccode\u003estatement_timeout\u003c/code\u003e, \u003ccode\u003eidle_in_transaction_session_timeout\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eUse prepared statements judiciously; for PgBouncer, prefer server-prepared off or use pgbouncer session mode.\u003c/li\u003e\n\u003cli\u003ePool instrumentation: queue wait time, checkout latency, timeouts.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"osdb-basics\"\u003eOS/DB basics\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep Postgres on same AZ/region; latency kills.\u003c/li\u003e\n\u003cli\u003eTune \u003ccode\u003ework_mem\u003c/code\u003e, \u003ccode\u003eshared_buffers\u003c/code\u003e, \u003ccode\u003eeffective_cache_size\u003c/code\u003e appropriately (DB side).\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003eEXPLAIN (ANALYZE, BUFFERS)\u003c/code\u003e in staging for heavy queries.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Pool sized and monitored; PgBouncer for many short connections.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Query timeouts set; slow logs monitored.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Key indexes present; pagination optimized.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e App-level metrics for pool wait, query latency, error rates.\u003c/li\u003e\n\u003c/ul\u003e","title":"Node.js + Postgres Performance Tuning"},{"content":"This note condenses the DEV article “Mastering Frontend Performance: Harnessing the Power of Caching” into actionable steps for modern apps.\nWhy cache Reduce network and CPU cost for repeated data/computation. Improve perceived speed and resilience to flaky networks. Keep UIs responsive under load. Layers to combine HTTP caching: set Cache-Control, ETag, Last-Modified, stale-while-revalidate for API/static responses; prefer immutable, versioned assets. Client memoization: cache expensive computations/render data (useMemo, useCallback, memoized selectors). Data caching: use React Query/SWR/Apollo to dedupe fetches, retry, refetch on focus. Service worker (when appropriate): offline/near-edge caching for shell + static assets. React hook hygiene Memoize derived data: useMemo(() =\u0026gt; heavyCompute(input), [input]). Memoize callbacks passed to children to avoid re-renders: useCallback(fn, deps). Keep props stable; avoid recreating objects/functions each render. HTTP cache playbook Static assets: long max-age + immutable on versioned filenames. APIs: choose strategy per route: idempotent reads: max-age/stale-while-revalidate with ETag. personalized or sensitive data: no-store. list endpoints: shorter max-age + revalidation. Prefer CDN edge caching; compress (Brotli) and serve modern formats (AVIF/WebP). UI checks No spinner longer than a couple of seconds; use skeletons and optimistic updates where safe. Avoid layout shift when cached data arrives—reserve space. Track Core Web Vitals (LCP/INP/CLS) and hit-rate for key caches. Quick checklist Versioned static assets + long-lived caching headers. API cache policy per route with ETag/stale-while-revalidate. React memoization for heavy work and stable callbacks. Data-layer cache (React Query/SWR) with sensible stale times + retries. RUM/CI dashboards watching Web Vitals and cache hit rates. Takeaway: Combine HTTP caching, client memoization, and data-layer caches to ship faster pages and keep them fast under real traffic.\n","permalink":"https://pixcave.com/posts/frontend-caching-playbook/","summary":"\u003cp\u003eThis note condenses the DEV article “Mastering Frontend Performance: Harnessing the Power of Caching” into actionable steps for modern apps.\u003c/p\u003e\n\u003ch2 id=\"why-cache\"\u003eWhy cache\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eReduce network and CPU cost for repeated data/computation.\u003c/li\u003e\n\u003cli\u003eImprove perceived speed and resilience to flaky networks.\u003c/li\u003e\n\u003cli\u003eKeep UIs responsive under load.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"layers-to-combine\"\u003eLayers to combine\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHTTP caching\u003c/strong\u003e: set \u003ccode\u003eCache-Control\u003c/code\u003e, \u003ccode\u003eETag\u003c/code\u003e, \u003ccode\u003eLast-Modified\u003c/code\u003e, \u003ccode\u003estale-while-revalidate\u003c/code\u003e for API/static responses; prefer immutable, versioned assets.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eClient memoization\u003c/strong\u003e: cache expensive computations/render data (\u003ccode\u003euseMemo\u003c/code\u003e, \u003ccode\u003euseCallback\u003c/code\u003e, memoized selectors).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eData caching\u003c/strong\u003e: use React Query/SWR/Apollo to dedupe fetches, retry, refetch on focus.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eService worker\u003c/strong\u003e (when appropriate): offline/near-edge caching for shell + static assets.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"react-hook-hygiene\"\u003eReact hook hygiene\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMemoize derived data: \u003ccode\u003euseMemo(() =\u0026gt; heavyCompute(input), [input])\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eMemoize callbacks passed to children to avoid re-renders: \u003ccode\u003euseCallback(fn, deps)\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eKeep props stable; avoid recreating objects/functions each render.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"http-cache-playbook\"\u003eHTTP cache playbook\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eStatic assets: long \u003ccode\u003emax-age\u003c/code\u003e + \u003ccode\u003eimmutable\u003c/code\u003e on versioned filenames.\u003c/li\u003e\n\u003cli\u003eAPIs: choose strategy per route:\n\u003cul\u003e\n\u003cli\u003eidempotent reads: \u003ccode\u003emax-age\u003c/code\u003e/\u003ccode\u003estale-while-revalidate\u003c/code\u003e with \u003ccode\u003eETag\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003epersonalized or sensitive data: \u003ccode\u003eno-store\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003elist endpoints: shorter \u003ccode\u003emax-age\u003c/code\u003e + revalidation.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003ePrefer CDN edge caching; compress (Brotli) and serve modern formats (AVIF/WebP).\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ui-checks\"\u003eUI checks\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eNo spinner longer than a couple of seconds; use skeletons and optimistic updates where safe.\u003c/li\u003e\n\u003cli\u003eAvoid layout shift when cached data arrives—reserve space.\u003c/li\u003e\n\u003cli\u003eTrack Core Web Vitals (LCP/INP/CLS) and hit-rate for key caches.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"quick-checklist\"\u003eQuick checklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Versioned static assets + long-lived caching headers.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e API cache policy per route with \u003ccode\u003eETag\u003c/code\u003e/\u003ccode\u003estale-while-revalidate\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e React memoization for heavy work and stable callbacks.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Data-layer cache (React Query/SWR) with sensible stale times + retries.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e RUM/CI dashboards watching Web Vitals and cache hit rates.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTakeaway:\u003c/strong\u003e Combine HTTP caching, client memoization, and data-layer caches to ship faster pages and keep them fast under real traffic.\u003c/p\u003e","title":"Caching for Frontend Performance: Practical Patterns"},{"content":"Deadlines \u0026amp; retries Require client deadlines; enforce server-side context with grpc.DeadlineExceeded handling. Configure retry/backoff on idempotent calls; avoid retry storms with jitter + max attempts. Interceptors Unary/stream interceptors for auth, metrics (Prometheus), logging, and panic recovery. Use per-RPC circuit breakers and rate limits for critical dependencies. TLS \u0026amp; auth Enable TLS everywhere; prefer mTLS for internal services. Rotate certs automatically; watch expiry metrics. Add authz checks in interceptors; propagate identity via metadata. Resource protection Limit concurrent streams and max message sizes. Bounded worker pools for handlers performing heavy work. Tune keepalive to detect dead peers without flapping. Observability Metrics: latency, error codes, message sizes, active streams, retries. Traces: annotate methods, peer info, attempt counts; sample smartly. Logs: structured fields for method, code, duration, peer. Checklist Deadlines required; retries only for idempotent calls with backoff. Interceptors for auth/metrics/logging/recovery. TLS/mTLS enabled; cert rotation automated. Concurrency and message limits set; keepalive tuned. ","permalink":"https://pixcave.com/posts/go-grpc-production-hardening/","summary":"\u003ch2 id=\"deadlines--retries\"\u003eDeadlines \u0026amp; retries\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRequire client deadlines; enforce server-side \u003ccode\u003econtext\u003c/code\u003e with \u003ccode\u003egrpc.DeadlineExceeded\u003c/code\u003e handling.\u003c/li\u003e\n\u003cli\u003eConfigure retry/backoff on idempotent calls; avoid retry storms with jitter + max attempts.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"interceptors\"\u003eInterceptors\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eUnary/stream interceptors for auth, metrics (Prometheus), logging, and panic recovery.\u003c/li\u003e\n\u003cli\u003eUse per-RPC circuit breakers and rate limits for critical dependencies.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"tls--auth\"\u003eTLS \u0026amp; auth\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEnable TLS everywhere; prefer mTLS for internal services.\u003c/li\u003e\n\u003cli\u003eRotate certs automatically; watch expiry metrics.\u003c/li\u003e\n\u003cli\u003eAdd authz checks in interceptors; propagate identity via metadata.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"resource-protection\"\u003eResource protection\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLimit concurrent streams and max message sizes.\u003c/li\u003e\n\u003cli\u003eBounded worker pools for handlers performing heavy work.\u003c/li\u003e\n\u003cli\u003eTune keepalive to detect dead peers without flapping.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMetrics: latency, error codes, message sizes, active streams, retries.\u003c/li\u003e\n\u003cli\u003eTraces: annotate methods, peer info, attempt counts; sample smartly.\u003c/li\u003e\n\u003cli\u003eLogs: structured fields for method, code, duration, peer.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Deadlines required; retries only for idempotent calls with backoff.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Interceptors for auth/metrics/logging/recovery.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e TLS/mTLS enabled; cert rotation automated.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Concurrency and message limits set; keepalive tuned.\u003c/li\u003e\n\u003c/ul\u003e","title":"Hardening gRPC Services in Go"},{"content":"Understanding Java class initialization order is crucial for avoiding subtle bugs. Here\u0026rsquo;s the real initialization sequence and common pitfalls.\nInitialization Order Static Fields and Blocks public class Example { // 1. Static fields initialized first private static int staticField = initializeStatic(); // 2. Static blocks executed in order static { System.out.println(\u0026#34;Static block 1\u0026#34;); } static { System.out.println(\u0026#34;Static block 2\u0026#34;); } private static int initializeStatic() { System.out.println(\u0026#34;Static field initialization\u0026#34;); return 1; } } Instance Fields and Constructors public class Example { // 3. Instance fields initialized private int instanceField = initializeInstance(); // 4. Instance initialization blocks { System.out.println(\u0026#34;Instance block\u0026#34;); } // 5. Constructor executed last public Example() { System.out.println(\u0026#34;Constructor\u0026#34;); } private int initializeInstance() { System.out.println(\u0026#34;Instance field initialization\u0026#34;); return 1; } } Complete Initialization Sequence public class InitializationDemo { // Step 1: Static fields private static String staticField = \u0026#34;Static field\u0026#34;; // Step 2: Static blocks (in order) static { System.out.println(\u0026#34;Static block 1\u0026#34;); } static { System.out.println(\u0026#34;Static block 2\u0026#34;); } // Step 3: Instance fields private String instanceField = \u0026#34;Instance field\u0026#34;; // Step 4: Instance blocks { System.out.println(\u0026#34;Instance block\u0026#34;); } // Step 5: Constructor public InitializationDemo() { System.out.println(\u0026#34;Constructor\u0026#34;); } } Common Pitfalls 1. Forward References // Bad: Forward reference public class BadExample { private int value = getValue(); // Error: forward reference private int multiplier = 10; private int getValue() { return multiplier * 2; // multiplier might not be initialized } } // Good: Initialize in correct order public class GoodExample { private int multiplier = 10; private int value = getValue(); private int getValue() { return multiplier * 2; } } 2. Static vs Instance Initialization public class ConfusingExample { private static int staticCounter = 0; private int instanceCounter = 0; static { staticCounter++; // Cannot access instanceCounter here! } { instanceCounter++; staticCounter++; // Can access static } } 3. Inheritance Initialization class Parent { static { System.out.println(\u0026#34;Parent static block\u0026#34;); } { System.out.println(\u0026#34;Parent instance block\u0026#34;); } public Parent() { System.out.println(\u0026#34;Parent constructor\u0026#34;); } } class Child extends Parent { static { System.out.println(\u0026#34;Child static block\u0026#34;); } { System.out.println(\u0026#34;Child instance block\u0026#34;); } public Child() { System.out.println(\u0026#34;Child constructor\u0026#34;); } } // Output order: // Parent static block // Child static block // Parent instance block // Parent constructor // Child instance block // Child constructor Best Practices Initialize fields in logical order Avoid forward references Keep initialization blocks simple Use constructors for complex initialization Document initialization dependencies Conclusion Understanding initialization order helps you:\nAvoid bugs from uninitialized fields Write predictable code Debug initialization issues Design better class hierarchies Master the initialization sequence to write better Java code! ☕\n","permalink":"https://pixcave.com/posts/java-initialization-order-pitfalls/","summary":"\u003cp\u003eUnderstanding Java class initialization order is crucial for avoiding subtle bugs. Here\u0026rsquo;s the real initialization sequence and common pitfalls.\u003c/p\u003e\n\u003ch2 id=\"initialization-order\"\u003eInitialization Order\u003c/h2\u003e\n\u003ch3 id=\"static-fields-and-blocks\"\u003eStatic Fields and Blocks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eExample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 1. Static fields initialized first\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e staticField \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e initializeStatic();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 2. Static blocks executed in order\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static block 1\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static block 2\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitializeStatic\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static field initialization\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e 1;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"instance-fields-and-constructors\"\u003eInstance Fields and Constructors\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eExample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 3. Instance fields initialized\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e instanceField \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e initializeInstance();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 4. Instance initialization blocks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Instance block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 5. Constructor executed last\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eExample\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Constructor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitializeInstance\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Instance field initialization\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e 1;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"complete-initialization-sequence\"\u003eComplete Initialization Sequence\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eInitializationDemo\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Step 1: Static fields\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e String staticField \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static field\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Step 2: Static blocks (in order)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static block 1\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Static block 2\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Step 3: Instance fields\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String instanceField \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Instance field\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Step 4: Instance blocks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Instance block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Step 5: Constructor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eInitializationDemo\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Constructor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-pitfalls\"\u003eCommon Pitfalls\u003c/h2\u003e\n\u003ch3 id=\"1-forward-references\"\u003e1. Forward References\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Forward reference\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBadExample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e getValue(); \u003cspan style=\"color:#75715e\"\u003e// Error: forward reference\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e multiplier \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetValue\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e multiplier \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e 2; \u003cspan style=\"color:#75715e\"\u003e// multiplier might not be initialized\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Initialize in correct order\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eGoodExample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e multiplier \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e getValue();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetValue\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e multiplier \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e 2;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-static-vs-instance-initialization\"\u003e2. Static vs Instance Initialization\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eConfusingExample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e staticCounter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e instanceCounter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        staticCounter\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Cannot access instanceCounter here!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        instanceCounter\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        staticCounter\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e// Can access static\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-inheritance-initialization\"\u003e3. Inheritance Initialization\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eParent\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Parent static block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Parent instance block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eParent\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Parent constructor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eChild\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e Parent {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Child static block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Child instance block\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eChild\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Child constructor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Output order:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Parent static block\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Child static block\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Parent instance block\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Parent constructor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Child instance block\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Child constructor\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eInitialize fields in logical order\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid forward references\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKeep initialization blocks simple\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse constructors for complex initialization\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDocument initialization dependencies\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eUnderstanding initialization order helps you:\u003c/p\u003e","title":"Java Class Initialization Order: Understanding the Real Sequence"},{"content":"Containerized systems have unique failure modes. Here\u0026rsquo;s how to identify and prevent common issues.\n1. Resource Exhaustion Memory Limits # docker-compose.yml services: app: deploy: resources: limits: memory: 512M reservations: memory: 256M CPU Throttling services: app: deploy: resources: limits: cpus: \u0026#39;1.0\u0026#39; 2. Container Restart Loops Health Checks # Dockerfile HEALTHCHECK --interval=30s --timeout=3s --start-period=40s \\ CMD curl -f http://localhost:8080/health || exit 1 Restart Policies services: app: restart: unless-stopped # Options: no, always, on-failure, unless-stopped 3. Network Issues Port Conflicts services: app: ports: - \u0026#34;8080:8080\u0026#34; # host:container DNS Resolution services: app: dns: - 8.8.8.8 - 8.8.4.4 4. Volume Mount Problems Permission Issues # Fix permissions RUN chown -R appuser:appuser /app USER appuser Volume Mounts services: app: volumes: - ./data:/app/data:ro # Read-only - cache:/app/cache 5. Image Layer Caching Optimize Dockerfile # Bad: Changes invalidate cache COPY . . RUN npm install # Good: Layer caching COPY package*.json ./ RUN npm install COPY . . 6. Log Management Log Rotation services: app: logging: driver: \u0026#34;json-file\u0026#34; options: max-size: \u0026#34;10m\u0026#34; max-file: \u0026#34;3\u0026#34; 7. Security Issues Non-Root User RUN useradd -m appuser USER appuser Secrets Management services: app: secrets: - db_password environment: DB_PASSWORD_FILE: /run/secrets/db_password Prevention Strategies Set resource limits Implement health checks Use proper restart policies Monitor container metrics Test failure scenarios Use orchestration tools (Kubernetes, Docker Swarm) Conclusion Prevent container failures by:\nResource management Health monitoring Proper configuration Security best practices Regular testing Build resilient containerized systems! 🐳\n","permalink":"https://pixcave.com/posts/containerized-systems-failure-modes/","summary":"\u003cp\u003eContainerized systems have unique failure modes. Here\u0026rsquo;s how to identify and prevent common issues.\u003c/p\u003e\n\u003ch2 id=\"1-resource-exhaustion\"\u003e1. Resource Exhaustion\u003c/h2\u003e\n\u003ch3 id=\"memory-limits\"\u003eMemory Limits\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# docker-compose.yml\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003edeploy\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eresources\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003elimits\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ememory\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e512M\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003ereservations\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ememory\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e256M\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"cpu-throttling\"\u003eCPU Throttling\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003edeploy\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eresources\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003elimits\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ecpus\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;1.0\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-container-restart-loops\"\u003e2. Container Restart Loops\u003c/h2\u003e\n\u003ch3 id=\"health-checks\"\u003eHealth Checks\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Dockerfile\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eHEALTHCHECK\u003c/span\u003e --interval\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e30s --timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e3s --start-period\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e40s \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e\u003c/span\u003e  CMD curl -f http://localhost:8080/health \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e exit \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"restart-policies\"\u003eRestart Policies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003erestart\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003eunless-stopped\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# Options: no, always, on-failure, unless-stopped\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-network-issues\"\u003e3. Network Issues\u003c/h2\u003e\n\u003ch3 id=\"port-conflicts\"\u003ePort Conflicts\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eports\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;8080:8080\u0026#34;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# host:container\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"dns-resolution\"\u003eDNS Resolution\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003edns\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003e8.8.8.8\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003e8.8.4.4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-volume-mount-problems\"\u003e4. Volume Mount Problems\u003c/h2\u003e\n\u003ch3 id=\"permission-issues\"\u003ePermission Issues\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Fix permissions\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e chown -R appuser:appuser /app\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eUSER\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eappuser\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"volume-mounts\"\u003eVolume Mounts\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003evolumes\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003e./data:/app/data:ro \u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e# Read-only\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003ecache:/app/cache\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-image-layer-caching\"\u003e5. Image Layer Caching\u003c/h2\u003e\n\u003ch3 id=\"optimize-dockerfile\"\u003eOptimize Dockerfile\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Bad: Changes invalidate cache\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm install\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Good: Layer caching\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e package*.json ./\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm install\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"6-log-management\"\u003e6. Log Management\u003c/h2\u003e\n\u003ch3 id=\"log-rotation\"\u003eLog Rotation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003elogging\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003edriver\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;json-file\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eoptions\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003emax-size\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10m\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003emax-file\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;3\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"7-security-issues\"\u003e7. Security Issues\u003c/h2\u003e\n\u003ch3 id=\"non-root-user\"\u003eNon-Root User\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e useradd -m appuser\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eUSER\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eappuser\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"secrets-management\"\u003eSecrets Management\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eservices\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003eapp\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003esecrets\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      - \u003cspan style=\"color:#ae81ff\"\u003edb_password\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003eenvironment\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003eDB_PASSWORD_FILE\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e/run/secrets/db_password\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"prevention-strategies\"\u003ePrevention Strategies\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSet resource limits\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eImplement health checks\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse proper restart policies\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor container metrics\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest failure scenarios\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse orchestration tools\u003c/strong\u003e (Kubernetes, Docker Swarm)\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003ePrevent container failures by:\u003c/p\u003e","title":"Common Failure Modes in Containerized Systems and Prevention"},{"content":"Effective testing in CI/CD pipelines requires balancing speed, coverage, and reliability. This guide covers strategies to optimize your testing approach for continuous integration and deployment.\nTesting pyramid for CI/CD The testing pyramid applies to CI/CD with some modifications:\n/\\ / \\ E2E Tests (few, slow, expensive) /____\\ / \\ Integration Tests (some, moderate) /________\\ / \\ Unit Tests (many, fast, cheap) /____________\\ CI/CD testing layers Unit tests: Fast, run on every commit Integration tests: Moderate speed, run on PRs E2E tests: Slow, run on main branch or scheduled Performance tests: Run periodically or on release candidates Pipeline testing strategy Stage 1: Pre-commit (local) Run fast checks before committing:\n# .pre-commit-config.yaml or package.json scripts scripts: \u0026#34;pre-commit\u0026#34;: \u0026#34;lint-staged \u0026amp;\u0026amp; npm run test:unit\u0026#34; What to include:\nLinting and formatting Unit tests (fast subset) Type checking Security scanning (basic) Stage 2: Pull request (CI) Run comprehensive checks on PRs:\n# .github/workflows/pr-checks.yml name: PR Checks on: [pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Unit Tests run: npm run test:unit -- --coverage - name: Integration Tests run: npm run test:integration - name: Lint run: npm run lint - name: Build run: npm run build What to include:\nAll unit tests with coverage Integration tests Build verification Code quality checks Dependency scanning Stage 3: Merge to main (pre-deploy) Run before deploying to staging:\njobs: pre-deploy: steps: - name: E2E Tests run: npm run test:e2e - name: Security Scan run: npm audit --audit-level=high - name: Performance Tests run: npm run test:performance What to include:\nE2E tests (critical paths) Security scanning Performance benchmarks Contract testing (if microservices) Stage 4: Post-deploy (validation) Verify deployment success:\njobs: smoke-tests: steps: - name: Health Check run: curl -f ${{ env.STAGING_URL }}/health - name: Smoke Tests run: npm run test:smoke -- --baseUrl=${{ env.STAGING_URL }} What to include:\nHealth checks Smoke tests (critical user flows) API availability checks Database connectivity Test execution strategies 1. Parallel execution Run tests in parallel to reduce total time:\n# Jest parallel execution module.exports = { maxWorkers: 4, testMatch: [\u0026#39;**/*.test.js\u0026#39;] }; # GitHub Actions matrix strategy strategy: matrix: test-group: [1, 2, 3, 4] steps: - run: npm run test -- --group=${{ matrix.test-group }} 2. Test sharding Split test suite into smaller chunks:\n# Split tests across multiple jobs npm run test -- --shard=1/4 # Run shard 1 of 4 npm run test -- --shard=2/4 # Run shard 2 of 4 3. Selective testing Run only relevant tests based on changes:\n# Only run tests for changed files - name: Changed Files uses: dorny/paths-filter@v2 id: changes with: filters: | frontend: - \u0026#39;frontend/**\u0026#39; backend: - \u0026#39;backend/**\u0026#39; - name: Frontend Tests if: steps.changes.outputs.frontend == \u0026#39;true\u0026#39; run: npm run test:frontend 4. Caching Cache dependencies and test results:\n- name: Cache dependencies uses: actions/cache@v3 with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles(\u0026#39;package-lock.json\u0026#39;) }} - name: Cache test results uses: actions/cache@v3 with: path: .jest-cache key: ${{ runner.os }}-jest-${{ hashFiles(\u0026#39;**/*.test.js\u0026#39;) }} Test types and when to run them Unit tests When: Every commit, every PR\nCharacteristics:\nFast (\u0026lt; 1 second per test) Isolated (no external dependencies) High coverage target (80%+) Example:\ndescribe(\u0026#39;UserService\u0026#39;, () =\u0026gt; { it(\u0026#39;should validate email format\u0026#39;, () =\u0026gt; { expect(validateEmail(\u0026#39;test@example.com\u0026#39;)).toBe(true); expect(validateEmail(\u0026#39;invalid\u0026#39;)).toBe(false); }); }); Integration tests When: On PR, before merge\nCharacteristics:\nModerate speed (seconds to minutes) Test component interactions Use test databases/containers Example:\ndescribe(\u0026#39;User API Integration\u0026#39;, () =\u0026gt; { it(\u0026#39;should create and retrieve user\u0026#39;, async () =\u0026gt; { const user = await createUser({ email: \u0026#39;test@example.com\u0026#39; }); const retrieved = await getUser(user.id); expect(retrieved.email).toBe(\u0026#39;test@example.com\u0026#39;); }); }); E2E tests When: On main branch, before production deploy\nCharacteristics:\nSlow (minutes to hours) Test complete user flows Run against staging environment Example:\ndescribe(\u0026#39;User Registration Flow\u0026#39;, () =\u0026gt; { it(\u0026#39;should complete registration\u0026#39;, async () =\u0026gt; { await page.goto(\u0026#39;/register\u0026#39;); await page.fill(\u0026#39;#email\u0026#39;, \u0026#39;test@example.com\u0026#39;); await page.fill(\u0026#39;#password\u0026#39;, \u0026#39;password123\u0026#39;); await page.click(\u0026#39;button[type=\u0026#34;submit\u0026#34;]\u0026#39;); await expect(page).toHaveURL(\u0026#39;/dashboard\u0026#39;); }); }); Performance tests When: Periodically, on release candidates\nCharacteristics:\nMeasure response times, throughput Identify regressions Run in isolated environment Example:\ndescribe(\u0026#39;API Performance\u0026#39;, () =\u0026gt; { it(\u0026#39;should respond within 200ms\u0026#39;, async () =\u0026gt; { const start = Date.now(); await api.get(\u0026#39;/users\u0026#39;); const duration = Date.now() - start; expect(duration).toBeLessThan(200); }); }); Optimizing test execution 1. Fail fast Stop on first failure for faster feedback:\nnpm run test -- --bail 2. Test prioritization Run critical tests first:\n// Jest: Run tests matching pattern first test.only(\u0026#39;critical user flow\u0026#39;, () =\u0026gt; { // This runs first }); 3. Skip flaky tests in CI // Skip known flaky tests in CI const isCI = process.env.CI === \u0026#39;true\u0026#39;; if (isCI) { test.skip(\u0026#39;flaky test\u0026#39;, () =\u0026gt; { // Skipped in CI }); } 4. Use test tags Tag tests by importance:\ndescribe(\u0026#39;Payment Processing\u0026#39;, () =\u0026gt; { it(\u0026#39;processes payment @critical\u0026#39;, () =\u0026gt; { // Always runs }); it(\u0026#39;handles edge case @low-priority\u0026#39;, () =\u0026gt; { // Runs less frequently }); }); Monitoring and metrics Key metrics to track Test execution time: Total pipeline duration Test pass rate: Percentage of passing tests Flaky test rate: Tests that fail intermittently Coverage trends: Code coverage over time Failure patterns: Common failure causes Setting up alerts # Alert on test failures - name: Notify on failure if: failure() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} text: \u0026#39;Tests failed in CI pipeline\u0026#39; Best practices 1. Keep tests fast Mock external dependencies Use in-memory databases Parallelize when possible Cache aggressively 2. Maintain test stability Avoid time-dependent tests Use fixed test data Clean up after tests Isolate test environments 3. Balance coverage and speed Aim for 80%+ unit test coverage Focus integration tests on critical paths Limit E2E tests to happy paths Use code coverage to identify gaps 4. Automate everything No manual test steps in CI/CD Self-healing tests where possible Automatic retry for transient failures Automatic rollback on test failure 5. Continuous improvement Review test execution times regularly Remove obsolete tests Refactor slow tests Update test strategies based on metrics Conclusion Effective CI/CD testing requires careful planning and continuous optimization. Balance speed with coverage, prioritize critical tests, and use parallel execution and caching to keep pipelines fast. Remember: Fast feedback is better than perfect coverage.\nThe goal is not to test everything in every pipeline run, but to catch issues early while maintaining deployment velocity.\n","permalink":"https://pixcave.com/posts/testing-strategies-cicd-pipelines/","summary":"\u003cp\u003eEffective testing in CI/CD pipelines requires balancing speed, coverage, and reliability. This guide covers strategies to optimize your testing approach for continuous integration and deployment.\u003c/p\u003e\n\u003ch2 id=\"testing-pyramid-for-cicd\"\u003eTesting pyramid for CI/CD\u003c/h2\u003e\n\u003cp\u003eThe testing pyramid applies to CI/CD with some modifications:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        /\\\n       /  \\     E2E Tests (few, slow, expensive)\n      /____\\\n     /      \\   Integration Tests (some, moderate)\n    /________\\\n   /          \\  Unit Tests (many, fast, cheap)\n  /____________\\\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"cicd-testing-layers\"\u003eCI/CD testing layers\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUnit tests\u003c/strong\u003e: Fast, run on every commit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIntegration tests\u003c/strong\u003e: Moderate speed, run on PRs\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eE2E tests\u003c/strong\u003e: Slow, run on main branch or scheduled\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePerformance tests\u003c/strong\u003e: Run periodically or on release candidates\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"pipeline-testing-strategy\"\u003ePipeline testing strategy\u003c/h2\u003e\n\u003ch3 id=\"stage-1-pre-commit-local\"\u003eStage 1: Pre-commit (local)\u003c/h3\u003e\n\u003cp\u003eRun fast checks before committing:\u003c/p\u003e","title":"Testing Strategies for CI/CD: Balancing Speed, Depth, and Sanity"},{"content":"When it shines IO-heavy workloads with many concurrent requests. Simplifies thread-per-request code without callback hell. Great for blocking JDBC (with drivers that release threads), HTTP clients, and file IO. Caveats Avoid blocking operations that pin VTs (synchronized blocks, some native calls). Watch libraries that block on locks; prefer async-friendly drivers when possible. Pinning shows as carrier thread exhaustion; monitor. Usage Executors: Executors.newVirtualThreadPerTaskExecutor(). For servers (e.g., Spring): set spring.threads.virtual.enabled=true (Spring Boot 3.2+). Keep per-request timeouts; use structured concurrency where possible. Observability Metrics: carrier thread pool usage, VT creation rate, blocked/pinned threads. Profiling: use JDK Flight Recorder; check for pinning events. Checklist Dependencies vetted for blocking/pinning. Timeouts on all IO; circuit breakers still apply. Dashboards for carrier thread utilization and pinning. Load test before prod; compare throughput/latency vs platform threads. ","permalink":"https://pixcave.com/posts/java-virtual-threads-loom/","summary":"\u003ch2 id=\"when-it-shines\"\u003eWhen it shines\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eIO-heavy workloads with many concurrent requests.\u003c/li\u003e\n\u003cli\u003eSimplifies thread-per-request code without callback hell.\u003c/li\u003e\n\u003cli\u003eGreat for blocking JDBC (with drivers that release threads), HTTP clients, and file IO.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"caveats\"\u003eCaveats\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAvoid blocking operations that pin VTs (synchronized blocks, some native calls).\u003c/li\u003e\n\u003cli\u003eWatch libraries that block on locks; prefer async-friendly drivers when possible.\u003c/li\u003e\n\u003cli\u003ePinning shows as carrier thread exhaustion; monitor.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"usage\"\u003eUsage\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eExecutors: \u003ccode\u003eExecutors.newVirtualThreadPerTaskExecutor()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eFor servers (e.g., Spring): set \u003ccode\u003espring.threads.virtual.enabled=true\u003c/code\u003e (Spring Boot 3.2+).\u003c/li\u003e\n\u003cli\u003eKeep per-request timeouts; use structured concurrency where possible.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMetrics: carrier thread pool usage, VT creation rate, blocked/pinned threads.\u003c/li\u003e\n\u003cli\u003eProfiling: use JDK Flight Recorder; check for pinning events.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Dependencies vetted for blocking/pinning.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Timeouts on all IO; circuit breakers still apply.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Dashboards for carrier thread utilization and pinning.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Load test before prod; compare throughput/latency vs platform threads.\u003c/li\u003e\n\u003c/ul\u003e","title":"Java Virtual Threads (Loom) for IO-heavy Services"},{"content":"The \u0026ldquo;object references an unsaved transient instance\u0026rdquo; error is common in Hibernate. Here\u0026rsquo;s how to fix it.\nUnderstanding the Error This error occurs when you try to save an entity that references another entity that hasn\u0026rsquo;t been persisted yet.\n// Error scenario User user = new User(); // Transient (not saved) Post post = new Post(); post.setUser(user); // References unsaved user postRepository.save(post); // Error! Solutions 1. Save Parent First // Save user first User user = new User(); user = userRepository.save(user); // Now managed Post post = new Post(); post.setUser(user); postRepository.save(post); // Works! 2. Use Cascade Types @Entity public class Post { @ManyToOne(cascade = CascadeType.PERSIST) private User user; } // Now saving post will save user too Post post = new Post(); post.setUser(new User()); postRepository.save(post); // Works! 3. Use @OneToMany with Cascade @Entity public class User { @OneToMany(mappedBy = \u0026#34;user\u0026#34;, cascade = CascadeType.ALL) private List\u0026lt;Post\u0026gt; posts; } User user = new User(); Post post = new Post(); user.getPosts().add(post); post.setUser(user); userRepository.save(user); // Saves both Common Patterns Bidirectional Relationships @Entity public class User { @OneToMany(mappedBy = \u0026#34;user\u0026#34;, cascade = CascadeType.ALL) private List\u0026lt;Post\u0026gt; posts = new ArrayList\u0026lt;\u0026gt;(); } @Entity public class Post { @ManyToOne @JoinColumn(name = \u0026#34;user_id\u0026#34;) private User user; // Helper method public void setUser(User user) { this.user = user; if (user != null \u0026amp;\u0026amp; !user.getPosts().contains(this)) { user.getPosts().add(this); } } } Best Practices Save parent entities first Use appropriate cascade types Maintain bidirectional relationships Use helper methods for relationships Handle null references Conclusion Fix Hibernate transient instance errors by:\nUnderstanding entity lifecycle Using cascade operations Proper relationship management Saving entities in correct order Master Hibernate relationships! 🔄\n","permalink":"https://pixcave.com/posts/java-hibernate-transient-instance-fix/","summary":"\u003cp\u003eThe \u0026ldquo;object references an unsaved transient instance\u0026rdquo; error is common in Hibernate. Here\u0026rsquo;s how to fix it.\u003c/p\u003e\n\u003ch2 id=\"understanding-the-error\"\u003eUnderstanding the Error\u003c/h2\u003e\n\u003cp\u003eThis error occurs when you try to save an entity that references another entity that hasn\u0026rsquo;t been persisted yet.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Error scenario\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e User(); \u003cspan style=\"color:#75715e\"\u003e// Transient (not saved)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePost post \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Post();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epost.\u003cspan style=\"color:#a6e22e\"\u003esetUser\u003c/span\u003e(user); \u003cspan style=\"color:#75715e\"\u003e// References unsaved user\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epostRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(post); \u003cspan style=\"color:#75715e\"\u003e// Error!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"solutions\"\u003eSolutions\u003c/h2\u003e\n\u003ch3 id=\"1-save-parent-first\"\u003e1. Save Parent First\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Save user first\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e User();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euser \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(user); \u003cspan style=\"color:#75715e\"\u003e// Now managed\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePost post \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Post();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epost.\u003cspan style=\"color:#a6e22e\"\u003esetUser\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epostRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(post); \u003cspan style=\"color:#75715e\"\u003e// Works!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-use-cascade-types\"\u003e2. Use Cascade Types\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePost\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@ManyToOne\u003c/span\u003e(cascade \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e CascadeType.\u003cspan style=\"color:#a6e22e\"\u003ePERSIST\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e User user;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Now saving post will save user too\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePost post \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Post();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epost.\u003cspan style=\"color:#a6e22e\"\u003esetUser\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e User());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epostRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(post); \u003cspan style=\"color:#75715e\"\u003e// Works!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-use-onetomany-with-cascade\"\u003e3. Use @OneToMany with Cascade\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@OneToMany\u003c/span\u003e(mappedBy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user\u0026#34;\u003c/span\u003e, cascade \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e CascadeType.\u003cspan style=\"color:#a6e22e\"\u003eALL\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePost\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e posts;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e User();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePost post \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Post();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euser.\u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(post);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epost.\u003cspan style=\"color:#a6e22e\"\u003esetUser\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euserRepository.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(user); \u003cspan style=\"color:#75715e\"\u003e// Saves both\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-patterns\"\u003eCommon Patterns\u003c/h2\u003e\n\u003ch3 id=\"bidirectional-relationships\"\u003eBidirectional Relationships\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@OneToMany\u003c/span\u003e(mappedBy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user\u0026#34;\u003c/span\u003e, cascade \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e CascadeType.\u003cspan style=\"color:#a6e22e\"\u003eALL\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePost\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e posts \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ArrayList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePost\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@ManyToOne\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@JoinColumn\u003c/span\u003e(name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;user_id\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e User user;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Helper method\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetUser\u003c/span\u003e(User user) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e user;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (user \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003euser.\u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003econtains\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            user.\u003cspan style=\"color:#a6e22e\"\u003egetPosts\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSave parent entities first\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse appropriate cascade types\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMaintain bidirectional relationships\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse helper methods for relationships\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle null references\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eFix Hibernate transient instance errors by:\u003c/p\u003e","title":"Hibernate: Fixing 'Object References an Unsaved Transient Instance' Error"},{"content":"The Java Collections Framework is essential for every Java developer. Here\u0026rsquo;s a comprehensive guide.\nCollection Hierarchy Collection ├── List │ ├── ArrayList │ ├── LinkedList │ └── Vector ├── Set │ ├── HashSet │ ├── LinkedHashSet │ └── TreeSet └── Queue ├── PriorityQueue └── Deque └── ArrayDeque Lists ArrayList List\u0026lt;String\u0026gt; list = new ArrayList\u0026lt;\u0026gt;(); list.add(\u0026#34;Java\u0026#34;); list.add(\u0026#34;Python\u0026#34;); list.get(0); // \u0026#34;Java\u0026#34; list.remove(0); LinkedList List\u0026lt;String\u0026gt; list = new LinkedList\u0026lt;\u0026gt;(); list.add(\u0026#34;First\u0026#34;); list.add(\u0026#34;Last\u0026#34;); // Better for frequent insertions/deletions Sets HashSet Set\u0026lt;String\u0026gt; set = new HashSet\u0026lt;\u0026gt;(); set.add(\u0026#34;Java\u0026#34;); set.add(\u0026#34;Java\u0026#34;); // Duplicate ignored set.contains(\u0026#34;Java\u0026#34;); // true TreeSet Set\u0026lt;String\u0026gt; set = new TreeSet\u0026lt;\u0026gt;(); set.add(\u0026#34;Zebra\u0026#34;); set.add(\u0026#34;Apple\u0026#34;); // Automatically sorted: [Apple, Zebra] Maps Map\u0026lt;String, Integer\u0026gt; map = new HashMap\u0026lt;\u0026gt;(); map.put(\u0026#34;Java\u0026#34;, 1); map.put(\u0026#34;Python\u0026#34;, 2); map.get(\u0026#34;Java\u0026#34;); // 1 map.containsKey(\u0026#34;Java\u0026#34;); // true Best Practices Use ArrayList for random access Use LinkedList for frequent insertions Use HashSet for unique elements Use TreeSet for sorted unique elements Use HashMap for key-value pairs Conclusion Master Java Collections to write efficient code! 📚\n","permalink":"https://pixcave.com/posts/java-collections-guide/","summary":"\u003cp\u003eThe Java Collections Framework is essential for every Java developer. Here\u0026rsquo;s a comprehensive guide.\u003c/p\u003e\n\u003ch2 id=\"collection-hierarchy\"\u003eCollection Hierarchy\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eCollection\n├── List\n│   ├── ArrayList\n│   ├── LinkedList\n│   └── Vector\n├── Set\n│   ├── HashSet\n│   ├── LinkedHashSet\n│   └── TreeSet\n└── Queue\n    ├── PriorityQueue\n    └── Deque\n        └── ArrayDeque\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"lists\"\u003eLists\u003c/h2\u003e\n\u003ch3 id=\"arraylist\"\u003eArrayList\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e list \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ArrayList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Python\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(0); \u003cspan style=\"color:#75715e\"\u003e// \u0026#34;Java\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eremove\u003c/span\u003e(0);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"linkedlist\"\u003eLinkedList\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e list \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e LinkedList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;First\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Last\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Better for frequent insertions/deletions\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"sets\"\u003eSets\u003c/h2\u003e\n\u003ch3 id=\"hashset\"\u003eHashSet\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSet\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e set \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e HashSet\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// Duplicate ignored\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset.\u003cspan style=\"color:#a6e22e\"\u003econtains\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// true\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"treeset\"\u003eTreeSet\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSet\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e set \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e TreeSet\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Zebra\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eset.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Apple\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Automatically sorted: [Apple, Zebra]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"maps\"\u003eMaps\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMap\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString, Integer\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e map \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e HashMap\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emap.\u003cspan style=\"color:#a6e22e\"\u003eput\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e, 1);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emap.\u003cspan style=\"color:#a6e22e\"\u003eput\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Python\u0026#34;\u003c/span\u003e, 2);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emap.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// 1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emap.\u003cspan style=\"color:#a6e22e\"\u003econtainsKey\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// true\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse ArrayList\u003c/strong\u003e for random access\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse LinkedList\u003c/strong\u003e for frequent insertions\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse HashSet\u003c/strong\u003e for unique elements\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse TreeSet\u003c/strong\u003e for sorted unique elements\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse HashMap\u003c/strong\u003e for key-value pairs\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMaster Java Collections to write efficient code! 📚\u003c/p\u003e","title":"Java Collections Framework: Complete Guide with Examples"},{"content":"Process manager modes pm=dynamic for most apps; pm=static only when workload is predictable and memory bounded. Key knobs: pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers. Size max_children = (available RAM - OS/webserver/DB) / avg worker RSS. Opcache Enable: opcache.enable=1, opcache.enable_cli=0, opcache.memory_consumption sized for codebase, opcache.interned_strings_buffer, opcache.max_accelerated_files. Avoid opcache.revalidate_freq=0 in prod unless you control deploy restarts; prefer deploy-triggered reloads. Timeouts \u0026amp; queues Keep request_terminate_timeout sane (e.g., 30s-60s); long requests move to queues. Use pm.max_requests to recycle leaky workers (e.g., 500-2000). Watch slowlog to catch blocking I/O or heavy CPU. Observability Export status_path and scrape: active/idle/slow requests, max children reached. Correlate with Nginx/Apache logs for upstream latency and 502/504s. Alert on max children reached, slowlog entries, and rising worker RSS. Checklist Pool sizing validated under load test. Opcache enabled and sized; reload on deploy. Timeouts/queues tuned; slowlog on. Status endpoint protected and scraped. ","permalink":"https://pixcave.com/posts/php-fpm-tuning-guide/","summary":"\u003ch2 id=\"process-manager-modes\"\u003eProcess manager modes\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003epm=dynamic\u003c/code\u003e for most apps; \u003ccode\u003epm=static\u003c/code\u003e only when workload is predictable and memory bounded.\u003c/li\u003e\n\u003cli\u003eKey knobs: \u003ccode\u003epm.max_children\u003c/code\u003e, \u003ccode\u003epm.start_servers\u003c/code\u003e, \u003ccode\u003epm.min_spare_servers\u003c/code\u003e, \u003ccode\u003epm.max_spare_servers\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eSize \u003ccode\u003emax_children\u003c/code\u003e = (available RAM - OS/webserver/DB) / avg worker RSS.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"opcache\"\u003eOpcache\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEnable: \u003ccode\u003eopcache.enable=1\u003c/code\u003e, \u003ccode\u003eopcache.enable_cli=0\u003c/code\u003e, \u003ccode\u003eopcache.memory_consumption\u003c/code\u003e sized for codebase, \u003ccode\u003eopcache.interned_strings_buffer\u003c/code\u003e, \u003ccode\u003eopcache.max_accelerated_files\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eAvoid \u003ccode\u003eopcache.revalidate_freq=0\u003c/code\u003e in prod unless you control deploy restarts; prefer deploy-triggered reloads.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"timeouts--queues\"\u003eTimeouts \u0026amp; queues\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eKeep \u003ccode\u003erequest_terminate_timeout\u003c/code\u003e sane (e.g., 30s-60s); long requests move to queues.\u003c/li\u003e\n\u003cli\u003eUse \u003ccode\u003epm.max_requests\u003c/code\u003e to recycle leaky workers (e.g., 500-2000).\u003c/li\u003e\n\u003cli\u003eWatch slowlog to catch blocking I/O or heavy CPU.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"observability\"\u003eObservability\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eExport \u003ccode\u003estatus_path\u003c/code\u003e and scrape: active/idle/slow requests, max children reached.\u003c/li\u003e\n\u003cli\u003eCorrelate with Nginx/Apache logs for upstream latency and 502/504s.\u003c/li\u003e\n\u003cli\u003eAlert on \u003ccode\u003emax children reached\u003c/code\u003e, slowlog entries, and rising worker RSS.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"checklist\"\u003eChecklist\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Pool sizing validated under load test.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Opcache enabled and sized; reload on deploy.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Timeouts/queues tuned; slowlog on.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Status endpoint protected and scraped.\u003c/li\u003e\n\u003c/ul\u003e","title":"PHP-FPM Tuning Guide"},{"content":"The N+1 problem is a common performance issue in JPA. Here\u0026rsquo;s how to solve it in Spring Data JPA.\nUnderstanding N+1 Problem // N+1 queries: 1 for users + N for each user\u0026#39;s posts List\u0026lt;User\u0026gt; users = userRepository.findAll(); for (User user : users) { List\u0026lt;Post\u0026gt; posts = postRepository.findByUserId(user.getId()); // N queries } Solutions 1. Eager Fetching @Entity public class User { @OneToMany(fetch = FetchType.EAGER) private List\u0026lt;Post\u0026gt; posts; } 2. Join Fetch (JPQL) @Query(\u0026#34;SELECT u FROM User u JOIN FETCH u.posts\u0026#34;) List\u0026lt;User\u0026gt; findAllWithPosts(); 3. Entity Graphs @EntityGraph(attributePaths = {\u0026#34;posts\u0026#34;}) @Query(\u0026#34;SELECT u FROM User u\u0026#34;) List\u0026lt;User\u0026gt; findAllWithPosts(); 4. Batch Fetching @Entity public class User { @BatchSize(size = 10) @OneToMany(fetch = FetchType.LAZY) private List\u0026lt;Post\u0026gt; posts; } Best Practices Use lazy loading by default Fetch associations when needed Use entity graphs Monitor query performance Use DTO projections Conclusion Solve N+1 problems with:\nEager fetching when appropriate Join fetch in queries Entity graphs for flexibility Batch fetching for optimization Optimize your JPA queries! ⚡\n","permalink":"https://pixcave.com/posts/spring-data-jpa-n1-problem/","summary":"\u003cp\u003eThe N+1 problem is a common performance issue in JPA. Here\u0026rsquo;s how to solve it in Spring Data JPA.\u003c/p\u003e\n\u003ch2 id=\"understanding-n1-problem\"\u003eUnderstanding N+1 Problem\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// N+1 queries: 1 for users + N for each user\u0026#39;s posts\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e users \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userRepository.\u003cspan style=\"color:#a6e22e\"\u003efindAll\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (User user : users) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePost\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e posts \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e postRepository.\u003cspan style=\"color:#a6e22e\"\u003efindByUserId\u003c/span\u003e(user.\u003cspan style=\"color:#a6e22e\"\u003egetId\u003c/span\u003e()); \u003cspan style=\"color:#75715e\"\u003e// N queries\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"solutions\"\u003eSolutions\u003c/h2\u003e\n\u003ch3 id=\"1-eager-fetching\"\u003e1. Eager Fetching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@OneToMany\u003c/span\u003e(fetch \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e FetchType.\u003cspan style=\"color:#a6e22e\"\u003eEAGER\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePost\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e posts;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"2-join-fetch-jpql\"\u003e2. Join Fetch (JPQL)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Query\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;SELECT u FROM User u JOIN FETCH u.posts\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindAllWithPosts\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"3-entity-graphs\"\u003e3. Entity Graphs\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@EntityGraph\u003c/span\u003e(attributePaths \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;posts\u0026#34;\u003c/span\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Query\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;SELECT u FROM User u\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindAllWithPosts\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"4-batch-fetching\"\u003e4. Batch Fetching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Entity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@BatchSize\u003c/span\u003e(size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 10)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@OneToMany\u003c/span\u003e(fetch \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e FetchType.\u003cspan style=\"color:#a6e22e\"\u003eLAZY\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e List\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePost\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e posts;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse lazy loading by default\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFetch associations when needed\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse entity graphs\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor query performance\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse DTO projections\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSolve N+1 problems with:\u003c/p\u003e","title":"Solving the N+1 Problem in Spring Data JPA"},{"content":"Spring WebFlux enables reactive programming in Spring. Here\u0026rsquo;s when and how to use it.\nWhen to Use WebFlux Use WebFlux When: High concurrency requirements Non-blocking I/O needed Streaming data Microservices with reactive backends Use MVC When: Traditional request-response Blocking operations Existing Spring MVC codebase Simpler mental model needed Basic Setup Dependencies \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-starter-webflux\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; Reactive Controller @RestController public class UserController { @GetMapping(\u0026#34;/users\u0026#34;) public Flux\u0026lt;User\u0026gt; getUsers() { return userService.findAll(); } @GetMapping(\u0026#34;/users/{id}\u0026#34;) public Mono\u0026lt;User\u0026gt; getUser(@PathVariable Long id) { return userService.findById(id); } @PostMapping(\u0026#34;/users\u0026#34;) public Mono\u0026lt;User\u0026gt; createUser(@RequestBody Mono\u0026lt;User\u0026gt; user) { return userService.save(user); } } Reactive Types Mono // Single value or empty Mono\u0026lt;String\u0026gt; mono = Mono.just(\u0026#34;Hello\u0026#34;); Mono\u0026lt;String\u0026gt; empty = Mono.empty(); Mono\u0026lt;String\u0026gt; error = Mono.error(new RuntimeException()); Flux // Multiple values Flux\u0026lt;String\u0026gt; flux = Flux.just(\u0026#34;A\u0026#34;, \u0026#34;B\u0026#34;, \u0026#34;C\u0026#34;); Flux\u0026lt;Integer\u0026gt; range = Flux.range(1, 10); Reactive Repository public interface UserRepository extends ReactiveCrudRepository\u0026lt;User, Long\u0026gt; { Flux\u0026lt;User\u0026gt; findByStatus(String status); Mono\u0026lt;User\u0026gt; findByEmail(String email); } Error Handling @GetMapping(\u0026#34;/users/{id}\u0026#34;) public Mono\u0026lt;User\u0026gt; getUser(@PathVariable Long id) { return userService.findById(id) .switchIfEmpty(Mono.error(new UserNotFoundException())) .onErrorResume(error -\u0026gt; { // Handle error return Mono.empty(); }); } Testing @SpringBootTest @AutoConfigureWebTestClient class UserControllerTest { @Autowired private WebTestClient webTestClient; @Test void shouldGetUsers() { webTestClient.get() .uri(\u0026#34;/users\u0026#34;) .exchange() .expectStatus().isOk() .expectBodyList(User.class); } } Best Practices Use reactive types throughout Avoid blocking operations Handle errors properly Use backpressure Monitor performance Conclusion Spring WebFlux provides:\nNon-blocking I/O High concurrency Reactive streams Better resource utilization Use WebFlux for reactive applications! ⚡\n","permalink":"https://pixcave.com/posts/spring-webflux-guide/","summary":"\u003cp\u003eSpring WebFlux enables reactive programming in Spring. Here\u0026rsquo;s when and how to use it.\u003c/p\u003e\n\u003ch2 id=\"when-to-use-webflux\"\u003eWhen to Use WebFlux\u003c/h2\u003e\n\u003ch3 id=\"use-webflux-when\"\u003eUse WebFlux When:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eHigh concurrency requirements\u003c/li\u003e\n\u003cli\u003eNon-blocking I/O needed\u003c/li\u003e\n\u003cli\u003eStreaming data\u003c/li\u003e\n\u003cli\u003eMicroservices with reactive backends\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"use-mvc-when\"\u003eUse MVC When:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eTraditional request-response\u003c/li\u003e\n\u003cli\u003eBlocking operations\u003c/li\u003e\n\u003cli\u003eExisting Spring MVC codebase\u003c/li\u003e\n\u003cli\u003eSimpler mental model needed\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"basic-setup\"\u003eBasic Setup\u003c/h2\u003e\n\u003ch3 id=\"dependencies\"\u003eDependencies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;dependency\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;groupId\u0026gt;\u003c/span\u003eorg.springframework.boot\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/groupId\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;artifactId\u0026gt;\u003c/span\u003espring-boot-starter-webflux\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/artifactId\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/dependency\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"reactive-controller\"\u003eReactive Controller\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RestController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserController\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e Flux\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUsers\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003efindAll\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e Mono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003efindById\u003c/span\u003e(id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@PostMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e Mono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e Mono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e user) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"reactive-types\"\u003eReactive Types\u003c/h2\u003e\n\u003ch3 id=\"mono\"\u003eMono\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Single value or empty\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e mono \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Mono.\u003cspan style=\"color:#a6e22e\"\u003ejust\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e empty \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Mono.\u003cspan style=\"color:#a6e22e\"\u003eempty\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e error \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Mono.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e RuntimeException());\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"flux\"\u003eFlux\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Multiple values\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFlux\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e flux \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Flux.\u003cspan style=\"color:#a6e22e\"\u003ejust\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;A\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;B\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;C\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFlux\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eInteger\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e range \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Flux.\u003cspan style=\"color:#a6e22e\"\u003erange\u003c/span\u003e(1, 10);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"reactive-repository\"\u003eReactive Repository\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRepository\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e ReactiveCrudRepository\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser, Long\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Flux\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindByStatus\u003c/span\u003e(String status);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Mono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindByEmail\u003c/span\u003e(String email);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"error-handling\"\u003eError Handling\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e Mono\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003efindById\u003c/span\u003e(id)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .\u003cspan style=\"color:#a6e22e\"\u003eswitchIfEmpty\u003c/span\u003e(Mono.\u003cspan style=\"color:#a6e22e\"\u003eerror\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e UserNotFoundException()))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .\u003cspan style=\"color:#a6e22e\"\u003eonErrorResume\u003c/span\u003e(error \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// Handle error\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e Mono.\u003cspan style=\"color:#a6e22e\"\u003eempty\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"testing\"\u003eTesting\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@SpringBootTest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@AutoConfigureWebTestClient\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserControllerTest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Autowired\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e WebTestClient webTestClient;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Test\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshouldGetUsers\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        webTestClient.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003euri\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eexchange\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eexpectStatus\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eisOk\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eexpectBodyList\u003c/span\u003e(User.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse reactive types throughout\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid blocking operations\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle errors properly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse backpressure\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor performance\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSpring WebFlux provides:\u003c/p\u003e","title":"Spring WebFlux: When to Use It and How to Build With It"},{"content":"Java has evolved significantly from Java 8 to Java 25. Here\u0026rsquo;s a comprehensive guide to the major changes.\nJava 8 (2014) Lambda Expressions List\u0026lt;String\u0026gt; names = Arrays.asList(\u0026#34;Java\u0026#34;, \u0026#34;Python\u0026#34;); names.forEach(name -\u0026gt; System.out.println(name)); Streams API List\u0026lt;String\u0026gt; filtered = names.stream() .filter(name -\u0026gt; name.startsWith(\u0026#34;J\u0026#34;)) .collect(Collectors.toList()); Optional Optional\u0026lt;String\u0026gt; name = Optional.of(\u0026#34;Java\u0026#34;); name.ifPresent(System.out::println); Java 9 (2017) Modules module com.example { requires java.base; exports com.example.api; } Private Methods in Interfaces interface MyInterface { default void method() { helper(); } private void helper() { // Private method } } Java 11 (2018) String Methods String text = \u0026#34; Java \u0026#34;; text.strip(); // \u0026#34;Java\u0026#34; text.repeat(3); // \u0026#34; Java Java Java \u0026#34; HTTP Client HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(\u0026#34;https://api.example.com\u0026#34;)) .build(); Java 17 (2021) Sealed Classes public sealed class Shape permits Circle, Rectangle { } public final class Circle extends Shape { } Pattern Matching if (obj instanceof String s) { System.out.println(s.length()); } Java 21 (2023) Virtual Threads Thread.ofVirtual().start(() -\u0026gt; { // Lightweight thread }); Pattern Matching for Switch String result = switch (value) { case Integer i -\u0026gt; \u0026#34;Integer: \u0026#34; + i; case String s -\u0026gt; \u0026#34;String: \u0026#34; + s; default -\u0026gt; \u0026#34;Unknown\u0026#34;; }; Java 25 (2025) Latest Features Enhanced pattern matching Improved performance Better memory management New API additions Migration Guide Update dependencies Test thoroughly Use new features gradually Monitor performance Update tooling Conclusion Java continues to evolve with:\nModern language features Performance improvements Better developer experience Enhanced security Stay updated with Java evolution! ☕\n","permalink":"https://pixcave.com/posts/java-8-to-java-25-evolution/","summary":"\u003cp\u003eJava has evolved significantly from Java 8 to Java 25. Here\u0026rsquo;s a comprehensive guide to the major changes.\u003c/p\u003e\n\u003ch2 id=\"java-8-2014\"\u003eJava 8 (2014)\u003c/h2\u003e\n\u003ch3 id=\"lambda-expressions\"\u003eLambda Expressions\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e names \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Arrays.\u003cspan style=\"color:#a6e22e\"\u003easList\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Python\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enames.\u003cspan style=\"color:#a6e22e\"\u003eforEach\u003c/span\u003e(name \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(name));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"streams-api\"\u003eStreams API\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e filtered \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e names.\u003cspan style=\"color:#a6e22e\"\u003estream\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003efilter\u003c/span\u003e(name \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e name.\u003cspan style=\"color:#a6e22e\"\u003estartsWith\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;J\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003ecollect\u003c/span\u003e(Collectors.\u003cspan style=\"color:#a6e22e\"\u003etoList\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"optional\"\u003eOptional\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOptional\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Optional.\u003cspan style=\"color:#a6e22e\"\u003eof\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Java\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ename.\u003cspan style=\"color:#a6e22e\"\u003eifPresent\u003c/span\u003e(System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e::println);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"java-9-2017\"\u003eJava 9 (2017)\u003c/h2\u003e\n\u003ch3 id=\"modules\"\u003eModules\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodule com.\u003cspan style=\"color:#a6e22e\"\u003eexample\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    requires java.\u003cspan style=\"color:#a6e22e\"\u003ebase\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    exports com.\u003cspan style=\"color:#a6e22e\"\u003eexample\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eapi\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"private-methods-in-interfaces\"\u003ePrivate Methods in Interfaces\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMyInterface\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emethod\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        helper();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehelper\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Private method\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"java-11-2018\"\u003eJava 11 (2018)\u003c/h2\u003e\n\u003ch3 id=\"string-methods\"\u003eString Methods\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString text \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;  Java  \u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etext.\u003cspan style=\"color:#a6e22e\"\u003estrip\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// \u0026#34;Java\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etext.\u003cspan style=\"color:#a6e22e\"\u003erepeat\u003c/span\u003e(3); \u003cspan style=\"color:#75715e\"\u003e// \u0026#34;  Java    Java    Java  \u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"http-client\"\u003eHTTP Client\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHttpClient client \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e HttpClient.\u003cspan style=\"color:#a6e22e\"\u003enewHttpClient\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHttpRequest request \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e HttpRequest.\u003cspan style=\"color:#a6e22e\"\u003enewBuilder\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003euri\u003c/span\u003e(URI.\u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://api.example.com\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"java-17-2021\"\u003eJava 17 (2021)\u003c/h2\u003e\n\u003ch3 id=\"sealed-classes\"\u003eSealed Classes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003esealed\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eShape\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    permits Circle, Rectangle {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCircle\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e Shape {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"pattern-matching\"\u003ePattern Matching\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (obj \u003cspan style=\"color:#66d9ef\"\u003einstanceof\u003c/span\u003e String s) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(s.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"java-21-2023\"\u003eJava 21 (2023)\u003c/h2\u003e\n\u003ch3 id=\"virtual-threads\"\u003eVirtual Threads\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThread.\u003cspan style=\"color:#a6e22e\"\u003eofVirtual\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e(() \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Lightweight thread\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"pattern-matching-for-switch\"\u003ePattern Matching for Switch\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (value) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e Integer i \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Integer: \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e i;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e String s \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;String: \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e s;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Unknown\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"java-25-2025\"\u003eJava 25 (2025)\u003c/h2\u003e\n\u003ch3 id=\"latest-features\"\u003eLatest Features\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eEnhanced pattern matching\u003c/li\u003e\n\u003cli\u003eImproved performance\u003c/li\u003e\n\u003cli\u003eBetter memory management\u003c/li\u003e\n\u003cli\u003eNew API additions\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"migration-guide\"\u003eMigration Guide\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUpdate dependencies\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest thoroughly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse new features gradually\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor performance\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUpdate tooling\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eJava continues to evolve with:\u003c/p\u003e","title":"Java Evolution: From Java 8 to Java 25 - Complete Guide"},{"content":"SOLID principles are fundamental to object-oriented design. Here\u0026rsquo;s how to apply them in Java.\nS - Single Responsibility Principle Bad class User { public void save() { } public void sendEmail() { } public void generateReport() { } } Good class User { // Only user data } class UserRepository { public void save(User user) { } } class EmailService { public void sendEmail(User user) { } } O - Open/Closed Principle Bad class AreaCalculator { public double calculateArea(Object shape) { if (shape instanceof Circle) { // Calculate circle area } else if (shape instanceof Rectangle) { // Calculate rectangle area } } } Good interface Shape { double calculateArea(); } class Circle implements Shape { public double calculateArea() { return Math.PI * radius * radius; } } class Rectangle implements Shape { public double calculateArea() { return width * height; } } L - Liskov Substitution Principle Bad class Bird { public void fly() { } } class Penguin extends Bird { public void fly() { throw new UnsupportedOperationException(); } } Good interface Bird { void eat(); } interface FlyingBird extends Bird { void fly(); } class Sparrow implements FlyingBird { public void fly() { } } class Penguin implements Bird { // No fly method } I - Interface Segregation Principle Bad interface Worker { void work(); void eat(); void sleep(); } class Robot implements Worker { public void eat() { } // Not applicable public void sleep() { } // Not applicable } Good interface Workable { void work(); } interface Eatable { void eat(); } class Human implements Workable, Eatable { public void work() { } public void eat() { } } class Robot implements Workable { public void work() { } } D - Dependency Inversion Principle Bad class UserService { private MySQLDatabase database; public UserService() { this.database = new MySQLDatabase(); } } Good interface Database { void save(User user); } class UserService { private Database database; public UserService(Database database) { this.database = database; } } Conclusion SOLID principles help you write:\nMaintainable code Extensible systems Testable components Flexible architectures Apply SOLID principles for better design! 🎯\n","permalink":"https://pixcave.com/posts/solid-principles-java-examples/","summary":"\u003cp\u003eSOLID principles are fundamental to object-oriented design. Here\u0026rsquo;s how to apply them in Java.\u003c/p\u003e\n\u003ch2 id=\"s---single-responsibility-principle\"\u003eS - Single Responsibility Principle\u003c/h2\u003e\n\u003ch3 id=\"bad\"\u003eBad\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esendEmail\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egenerateReport\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"good\"\u003eGood\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Only user data\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRepository\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(User user) { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEmailService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esendEmail\u003c/span\u003e(User user) { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"o---openclosed-principle\"\u003eO - Open/Closed Principle\u003c/h2\u003e\n\u003ch3 id=\"bad-1\"\u003eBad\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAreaCalculator\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecalculateArea\u003c/span\u003e(Object shape) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (shape \u003cspan style=\"color:#66d9ef\"\u003einstanceof\u003c/span\u003e Circle) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// Calculate circle area\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (shape \u003cspan style=\"color:#66d9ef\"\u003einstanceof\u003c/span\u003e Rectangle) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// Calculate rectangle area\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"good-1\"\u003eGood\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eShape\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecalculateArea\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCircle\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Shape {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecalculateArea\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e Math.\u003cspan style=\"color:#a6e22e\"\u003ePI\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e radius \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e radius;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRectangle\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Shape {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecalculateArea\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e height;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"l---liskov-substitution-principle\"\u003eL - Liskov Substitution Principle\u003c/h2\u003e\n\u003ch3 id=\"bad-2\"\u003eBad\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBird\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efly\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePenguin\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e Bird {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efly\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethrow\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e UnsupportedOperationException();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"good-2\"\u003eGood\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBird\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eeat\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eFlyingBird\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e Bird {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efly\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSparrow\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e FlyingBird {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efly\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePenguin\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Bird {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// No fly method\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"i---interface-segregation-principle\"\u003eI - Interface Segregation Principle\u003c/h2\u003e\n\u003ch3 id=\"bad-3\"\u003eBad\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWorker\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ework\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eeat\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRobot\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Worker {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eeat\u003c/span\u003e() { } \u003cspan style=\"color:#75715e\"\u003e// Not applicable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e() { } \u003cspan style=\"color:#75715e\"\u003e// Not applicable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"good-3\"\u003eGood\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWorkable\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ework\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEatable\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eeat\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eHuman\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Workable, Eatable {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ework\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eeat\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRobot\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e Workable {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ework\u003c/span\u003e() { }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"d---dependency-inversion-principle\"\u003eD - Dependency Inversion Principle\u003c/h2\u003e\n\u003ch3 id=\"bad-4\"\u003eBad\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e MySQLDatabase database;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edatabase\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e MySQLDatabase();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"good-4\"\u003eGood\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDatabase\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esave\u003c/span\u003e(User user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Database database;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserService\u003c/span\u003e(Database database) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edatabase\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e database;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSOLID principles help you write:\u003c/p\u003e","title":"SOLID Principles Explained with Java Examples"},{"content":"Java is often criticized for verbosity, but modern Java can be concise. Here\u0026rsquo;s how to write cleaner code.\nModern Java Features Records (Java 14+) // Old way public class User { private String name; private String email; public User(String name, String email) { this.name = name; this.email = email; } // Getters, equals, hashCode, toString... } // New way public record User(String name, String email) { } Pattern Matching (Java 17+) // Old way if (obj instanceof String) { String s = (String) obj; System.out.println(s.length()); } // New way if (obj instanceof String s) { System.out.println(s.length()); } Switch Expressions (Java 14+) // Old way String result; switch (day) { case MONDAY: case FRIDAY: result = \u0026#34;Weekday\u0026#34;; break; default: result = \u0026#34;Weekend\u0026#34;; } // New way String result = switch (day) { case MONDAY, FRIDAY -\u0026gt; \u0026#34;Weekday\u0026#34;; default -\u0026gt; \u0026#34;Weekend\u0026#34;; }; Best Practices Use Streams // Old way List\u0026lt;String\u0026gt; filtered = new ArrayList\u0026lt;\u0026gt;(); for (String name : names) { if (name.startsWith(\u0026#34;J\u0026#34;)) { filtered.add(name.toUpperCase()); } } // New way List\u0026lt;String\u0026gt; filtered = names.stream() .filter(name -\u0026gt; name.startsWith(\u0026#34;J\u0026#34;)) .map(String::toUpperCase) .toList(); Use Optional // Old way String result = null; if (user != null \u0026amp;\u0026amp; user.getName() != null) { result = user.getName().toUpperCase(); } // New way String result = Optional.ofNullable(user) .map(User::getName) .map(String::toUpperCase) .orElse(null); Conclusion Modern Java is concise when you:\nUse records for data classes Use pattern matching Use streams for collections Use Optional for null handling Follow best practices Write concise, modern Java! ☕\n","permalink":"https://pixcave.com/posts/java-verbosity-myth/","summary":"\u003cp\u003eJava is often criticized for verbosity, but modern Java can be concise. Here\u0026rsquo;s how to write cleaner code.\u003c/p\u003e\n\u003ch2 id=\"modern-java-features\"\u003eModern Java Features\u003c/h2\u003e\n\u003ch3 id=\"records-java-14\"\u003eRecords (Java 14+)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Old way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String email;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e(String name, String email) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e email;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Getters, equals, hashCode, toString...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// New way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003erecord\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e(String name, String email) { }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"pattern-matching-java-17\"\u003ePattern Matching (Java 17+)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Old way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (obj \u003cspan style=\"color:#66d9ef\"\u003einstanceof\u003c/span\u003e String) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    String s \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (String) obj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(s.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// New way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (obj \u003cspan style=\"color:#66d9ef\"\u003einstanceof\u003c/span\u003e String s) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(s.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"switch-expressions-java-14\"\u003eSwitch Expressions (Java 14+)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Old way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString result;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (day) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e MONDAY:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e FRIDAY:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Weekday\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Weekend\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// New way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (day) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e MONDAY, FRIDAY \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Weekday\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Weekend\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003ch3 id=\"use-streams\"\u003eUse Streams\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Old way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e filtered \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ArrayList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (String name : names) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (name.\u003cspan style=\"color:#a6e22e\"\u003estartsWith\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;J\u0026#34;\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        filtered.\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(name.\u003cspan style=\"color:#a6e22e\"\u003etoUpperCase\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// New way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eList\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e filtered \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e names.\u003cspan style=\"color:#a6e22e\"\u003estream\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003efilter\u003c/span\u003e(name \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e name.\u003cspan style=\"color:#a6e22e\"\u003estartsWith\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;J\u0026#34;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(String::toUpperCase)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003etoList\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"use-optional\"\u003eUse Optional\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Old way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (user \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e user.\u003cspan style=\"color:#a6e22e\"\u003egetName\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e user.\u003cspan style=\"color:#a6e22e\"\u003egetName\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003etoUpperCase\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// New way\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eString result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Optional.\u003cspan style=\"color:#a6e22e\"\u003eofNullable\u003c/span\u003e(user)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(User::getName)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003emap\u003c/span\u003e(String::toUpperCase)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003eorElse\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eModern Java is concise when you:\u003c/p\u003e","title":"Java Isn't Verbose - You Are: Writing Concise Java Code"},{"content":"This article summarizes the DEV post “Key Performance Metrics for Web Apps and How to Measure Them,” focusing on the most important signals and how to capture them.\nCore metrics LCP (Largest Contentful Paint): loading speed; target \u0026lt; 2.5s p75. INP/TTI (Interaction to Next Paint / Time to Interactive): interactivity; target INP \u0026lt; 200ms p75. FCP (First Contentful Paint): first visual response. TTFB (Time to First Byte): server responsiveness. Bundle size \u0026amp; request count: total transferred bytes and requests. Measurement toolbox Lighthouse: automated audits; budgets and suggestions. WebPageTest: multi-location runs, filmstrips, waterfalls. RUM (GA or custom): real-user timing for live traffic. React profiler \u0026amp; perf tools: find slow renders/update frequency. Webpack/Vite bundle analyzer: visualize bundle composition and dead weight. Optimization reminders Ship less JS/CSS; enable tree shaking/code splitting. Compress and cache static assets; serve modern image formats. Trim request count; inline critical CSS for hero; defer non-critical JS. Watch layout stability; reserve space to avoid CLS hits. Set and enforce budgets (JS gz \u0026lt; 200KB, LCP \u0026lt; 2.5s p75, INP \u0026lt; 200ms). Takeaway: Track a small, high-signal set of metrics with both lab (Lighthouse/WPT) and field (RUM) data, then enforce budgets so regressions fail fast.\n","permalink":"https://pixcave.com/posts/webapp-performance-metrics/","summary":"\u003cp\u003eThis article summarizes the DEV post “Key Performance Metrics for Web Apps and How to Measure Them,” focusing on the most important signals and how to capture them.\u003c/p\u003e\n\u003ch2 id=\"core-metrics\"\u003eCore metrics\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eLCP (Largest Contentful Paint):\u003c/strong\u003e loading speed; target \u0026lt; 2.5s p75.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eINP/TTI (Interaction to Next Paint / Time to Interactive):\u003c/strong\u003e interactivity; target INP \u0026lt; 200ms p75.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFCP (First Contentful Paint):\u003c/strong\u003e first visual response.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTTFB (Time to First Byte):\u003c/strong\u003e server responsiveness.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBundle size \u0026amp; request count:\u003c/strong\u003e total transferred bytes and requests.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"measurement-toolbox\"\u003eMeasurement toolbox\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eLighthouse:\u003c/strong\u003e automated audits; budgets and suggestions.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWebPageTest:\u003c/strong\u003e multi-location runs, filmstrips, waterfalls.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eRUM (GA or custom):\u003c/strong\u003e real-user timing for live traffic.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eReact profiler \u0026amp; perf tools:\u003c/strong\u003e find slow renders/update frequency.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWebpack/Vite bundle analyzer:\u003c/strong\u003e visualize bundle composition and dead weight.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"optimization-reminders\"\u003eOptimization reminders\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eShip less JS/CSS; enable tree shaking/code splitting.\u003c/li\u003e\n\u003cli\u003eCompress and cache static assets; serve modern image formats.\u003c/li\u003e\n\u003cli\u003eTrim request count; inline critical CSS for hero; defer non-critical JS.\u003c/li\u003e\n\u003cli\u003eWatch layout stability; reserve space to avoid CLS hits.\u003c/li\u003e\n\u003cli\u003eSet and enforce budgets (JS gz \u0026lt; 200KB, LCP \u0026lt; 2.5s p75, INP \u0026lt; 200ms).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eTakeaway:\u003c/strong\u003e Track a small, high-signal set of metrics with both lab (Lighthouse/WPT) and field (RUM) data, then enforce budgets so regressions fail fast.\u003c/p\u003e","title":"Web App Performance Metrics and How to Measure Them"},{"content":"Validation is crucial in Spring Boot applications. Here\u0026rsquo;s a complete guide to using @Valid and @Validated.\nBasic Validation Dependencies \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-starter-validation\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; Bean Validation public class CreateUserRequest { @NotBlank(message = \u0026#34;Name is required\u0026#34;) private String name; @Email(message = \u0026#34;Invalid email format\u0026#34;) @NotBlank private String email; @Min(value = 18, message = \u0026#34;Age must be at least 18\u0026#34;) @Max(value = 120, message = \u0026#34;Age must be at most 120\u0026#34;) private Integer age; } @Valid vs @Validated @Valid @PostMapping(\u0026#34;/users\u0026#34;) public ResponseEntity\u0026lt;User\u0026gt; createUser(@Valid @RequestBody CreateUserRequest request) { // Validates request object } @Validated @RestController @Validated public class UserController { @GetMapping(\u0026#34;/users/{id}\u0026#34;) public User getUser(@PathVariable @Min(1) Long id) { // Validates path variable } } Custom Validators @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PhoneNumberValidator.class) public @interface PhoneNumber { String message() default \u0026#34;Invalid phone number\u0026#34;; Class\u0026lt;?\u0026gt;[] groups() default {}; Class\u0026lt;? extends Payload\u0026gt;[] payload() default {}; } public class PhoneNumberValidator implements ConstraintValidator\u0026lt;PhoneNumber, String\u0026gt; { @Override public boolean isValid(String value, ConstraintValidatorContext context) { return value != null \u0026amp;\u0026amp; value.matches(\u0026#34;^\\\\+?[1-9]\\\\d{1,14}$\u0026#34;); } } Validation Groups public interface CreateGroup {} public interface UpdateGroup {} public class UserRequest { @NotNull(groups = UpdateGroup.class) private Long id; @NotBlank(groups = {CreateGroup.class, UpdateGroup.class}) private String name; } @PostMapping(\u0026#34;/users\u0026#34;) public ResponseEntity\u0026lt;User\u0026gt; create(@Validated(CreateGroup.class) @RequestBody UserRequest request) { // Only validates CreateGroup fields } Error Handling @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity\u0026lt;ErrorResponse\u0026gt; handleValidation( MethodArgumentNotValidException ex) { Map\u0026lt;String, String\u0026gt; errors = new HashMap\u0026lt;\u0026gt;(); ex.getBindingResult().getFieldErrors().forEach(error -\u0026gt; errors.put(error.getField(), error.getDefaultMessage()) ); return ResponseEntity.badRequest() .body(new ErrorResponse(\u0026#34;Validation failed\u0026#34;, errors)); } } Best Practices Validate at controller level Use appropriate annotations Create custom validators Handle validation errors Use validation groups Conclusion Spring Boot validation provides:\nDeclarative validation Custom validators Error handling Type safety Validate your data properly! ✅\n","permalink":"https://pixcave.com/posts/spring-boot-validation-complete-guide/","summary":"\u003cp\u003eValidation is crucial in Spring Boot applications. Here\u0026rsquo;s a complete guide to using @Valid and @Validated.\u003c/p\u003e\n\u003ch2 id=\"basic-validation\"\u003eBasic Validation\u003c/h2\u003e\n\u003ch3 id=\"dependencies\"\u003eDependencies\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;dependency\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;groupId\u0026gt;\u003c/span\u003eorg.springframework.boot\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/groupId\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;artifactId\u0026gt;\u003c/span\u003espring-boot-starter-validation\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/artifactId\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/dependency\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"bean-validation\"\u003eBean Validation\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCreateUserRequest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotBlank\u003c/span\u003e(message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Name is required\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Email\u003c/span\u003e(message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid email format\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotBlank\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String email;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Min\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 18, message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Age must be at least 18\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Max\u003c/span\u003e(value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 120, message \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Age must be at most 120\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Integer age;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"valid-vs-validated\"\u003e@Valid vs @Validated\u003c/h2\u003e\n\u003ch3 id=\"valid\"\u003e@Valid\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@PostMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@Valid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e CreateUserRequest request) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Validates request object\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"validated\"\u003e@Validated\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RestController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Validated\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserController\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@GetMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users/{id}\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e User \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@PathVariable\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Min\u003c/span\u003e(1) Long id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Validates path variable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"custom-validators\"\u003eCustom Validators\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Target\u003c/span\u003e({ElementType.\u003cspan style=\"color:#a6e22e\"\u003eFIELD\u003c/span\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Retention\u003c/span\u003e(RetentionPolicy.\u003cspan style=\"color:#a6e22e\"\u003eRUNTIME\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Constraint\u003c/span\u003e(validatedBy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e PhoneNumberValidator.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@interface\u003c/span\u003e PhoneNumber {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    String \u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e() \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Invalid phone number\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Class\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u0026gt;[]\u003c/span\u003e groups() \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e {};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Class\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e Payload\u003cspan style=\"color:#f92672\"\u003e\u0026gt;[]\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epayload\u003c/span\u003e() \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e {};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePhoneNumberValidator\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eimplements\u003c/span\u003e ConstraintValidator\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ePhoneNumber, String\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Override\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eboolean\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eisValid\u003c/span\u003e(String value, ConstraintValidatorContext context) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e value \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e value.\u003cspan style=\"color:#a6e22e\"\u003ematches\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;^\\\\+?[1-9]\\\\d{1,14}$\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"validation-groups\"\u003eValidation Groups\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCreateGroup\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUpdateGroup\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUserRequest\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotNull\u003c/span\u003e(groups \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e UpdateGroup.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Long id;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@NotBlank\u003c/span\u003e(groups \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {CreateGroup.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e, UpdateGroup.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e String name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@PostMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@Validated\u003c/span\u003e(CreateGroup.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e UserRequest request) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Only validates CreateGroup fields\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"error-handling\"\u003eError Handling\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@RestControllerAdvice\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eGlobalExceptionHandler\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@ExceptionHandler\u003c/span\u003e(MethodArgumentNotValidException.\u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e ResponseEntity\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eErrorResponse\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleValidation\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            MethodArgumentNotValidException ex) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Map\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString, String\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e errors \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e HashMap\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ex.\u003cspan style=\"color:#a6e22e\"\u003egetBindingResult\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003egetFieldErrors\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eforEach\u003c/span\u003e(error \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            errors.\u003cspan style=\"color:#a6e22e\"\u003eput\u003c/span\u003e(error.\u003cspan style=\"color:#a6e22e\"\u003egetField\u003c/span\u003e(), error.\u003cspan style=\"color:#a6e22e\"\u003egetDefaultMessage\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ResponseEntity.\u003cspan style=\"color:#a6e22e\"\u003ebadRequest\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e ErrorResponse(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Validation failed\u0026#34;\u003c/span\u003e, errors));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eValidate at controller level\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse appropriate annotations\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCreate custom validators\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle validation errors\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse validation groups\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eSpring Boot validation provides:\u003c/p\u003e","title":"Spring Boot Validation: Complete Guide with @Valid and @Validated"},{"content":"MongoDB performance optimization requires a systematic approach to identify bottlenecks, analyze query patterns, and implement effective indexing strategies. This guide covers profiling techniques, index optimization, and load testing methodologies.\nUnderstanding MongoDB performance MongoDB performance depends on several factors:\nQuery patterns: How queries are structured and what operations they perform Index usage: Whether queries can leverage indexes effectively Data volume: Size of collections and documents Hardware resources: CPU, memory, and disk I/O capacity Connection pooling: How applications manage database connections Profiling MongoDB queries Enable profiling MongoDB\u0026rsquo;s profiler collects detailed information about query execution:\n// Enable profiling for slow queries (\u0026gt;100ms) db.setProfilingLevel(1, { slowms: 100 }); // Profile all operations (use with caution in production) db.setProfilingLevel(2); // Disable profiling db.setProfilingLevel(0); Analyze profiler data // Find slowest queries db.system.profile.find().sort({ millis: -1 }).limit(10).pretty(); // Find queries without indexes db.system.profile.find({ \u0026#34;execStats.stage\u0026#34;: \u0026#34;COLLSCAN\u0026#34; }).pretty(); // Analyze query patterns db.system.profile.aggregate([ { $group: { _id: \u0026#34;$command\u0026#34;, avgDuration: { $avg: \u0026#34;$millis\u0026#34; }, count: { $sum: 1 } }}, { $sort: { avgDuration: -1 } } ]); Index optimization strategies 1. Compound indexes Create indexes that match your query patterns:\n// Query: find users by email and status db.users.find({ email: \u0026#34;user@example.com\u0026#34;, status: \u0026#34;active\u0026#34; }); // Optimal index db.users.createIndex({ email: 1, status: 1 }); // Query with sort db.users.find({ email: \u0026#34;user@example.com\u0026#34; }).sort({ createdAt: -1 }); // Index should include sort field db.users.createIndex({ email: 1, createdAt: -1 }); 2. Index selectivity Prioritize indexes on high-selectivity fields:\n// High selectivity: email (unique or near-unique) db.users.createIndex({ email: 1 }); // Low selectivity: status (few distinct values) // Use in compound indexes, not alone db.users.createIndex({ status: 1, createdAt: -1 }); 3. Partial indexes Index only documents matching a condition:\n// Index only active users db.users.createIndex( { email: 1 }, { partialFilterExpression: { status: \u0026#34;active\u0026#34; } } ); 4. Text indexes For full-text search:\ndb.articles.createIndex({ title: \u0026#34;text\u0026#34;, content: \u0026#34;text\u0026#34; }); // Search db.articles.find({ $text: { $search: \u0026#34;mongodb performance\u0026#34; } }); Query optimization techniques 1. Use projection to limit fields // Bad: fetches all fields db.users.find({ email: \u0026#34;user@example.com\u0026#34; }); // Good: only fetch needed fields db.users.find( { email: \u0026#34;user@example.com\u0026#34; }, { name: 1, email: 1, _id: 0 } ); 2. Limit result sets // Always use limit for large collections db.products.find({ category: \u0026#34;electronics\u0026#34; }) .sort({ price: 1 }) .limit(20); 3. Use covered queries Queries that can be satisfied entirely from indexes:\n// Index db.orders.createIndex({ customerId: 1, orderDate: -1, total: 1 }); // Covered query (only uses index, no collection scan) db.orders.find( { customerId: \u0026#34;12345\u0026#34; }, { customerId: 1, orderDate: 1, total: 1, _id: 0 } ); 4. Avoid regex at start of string // Bad: can\u0026#39;t use index db.users.find({ email: /^.*@example\\.com$/ }); // Good: can use index db.users.find({ email: /^user@example\\.com$/ }); Load testing with JMeter Setup JMeter for MongoDB Install MongoDB JDBC driver Configure JDBC connection Create test plans for common queries Sample JMeter test plan \u0026lt;!-- MongoDB connection configuration --\u0026gt; \u0026lt;JDBCDataSource\u0026gt; \u0026lt;stringProp name=\u0026#34;dataSource\u0026#34;\u0026gt;mongodb://localhost:27017/testdb\u0026lt;/stringProp\u0026gt; \u0026lt;stringProp name=\u0026#34;queryType\u0026#34;\u0026gt;Select Statement\u0026lt;/stringProp\u0026gt; \u0026lt;stringProp name=\u0026#34;query\u0026#34;\u0026gt;db.users.find({ email: \u0026#34;${email}\u0026#34; })\u0026lt;/stringProp\u0026gt; \u0026lt;/JDBCDataSource\u0026gt; Performance metrics to monitor Response time: Average, p90, p99 latencies Throughput: Queries per second Error rate: Failed queries percentage Resource usage: CPU, memory, disk I/O Common performance issues 1. Collection scans Symptom: Queries show COLLSCAN in execution stats\nSolution: Create appropriate indexes\n// Check for collection scans db.users.find({ name: \u0026#34;John\u0026#34; }).explain(\u0026#34;executionStats\u0026#34;); // If stage is \u0026#34;COLLSCAN\u0026#34;, create index db.users.createIndex({ name: 1 }); 2. Inefficient indexes Symptom: Index exists but query still slow\nSolution: Verify index usage and order\n// Check index usage db.users.find({ email: \u0026#34;user@example.com\u0026#34;, status: \u0026#34;active\u0026#34; }) .explain(\u0026#34;executionStats\u0026#34;); // Ensure index field order matches query db.users.createIndex({ email: 1, status: 1 }); // Correct order 3. Large documents Symptom: High memory usage, slow queries\nSolution: Normalize data, use references\n// Instead of embedding large arrays { userId: \u0026#34;123\u0026#34;, orders: [/* 1000 orders */] } // Use references { userId: \u0026#34;123\u0026#34; } // Separate orders collection { userId: \u0026#34;123\u0026#34;, orderId: \u0026#34;456\u0026#34;, // order details } Monitoring and maintenance Key metrics to track Query execution time: Average and p99 latencies Index hit ratio: Percentage of queries using indexes Collection scan ratio: Percentage of queries scanning collections Connection pool usage: Active vs available connections Cache hit ratio: WiredTiger cache efficiency Regular maintenance tasks Analyze slow queries: Review profiler data weekly Review index usage: Remove unused indexes Update statistics: Run db.collection.stats() regularly Monitor disk space: Indexes consume storage Optimize sharding: For large deployments Best practices summary Profile first: Enable profiling to identify slow queries Index strategically: Create indexes based on query patterns Use compound indexes: Match query and sort patterns Limit result sets: Always use .limit() for large collections Project fields: Only fetch needed fields Monitor continuously: Set up alerts for performance degradation Test under load: Use JMeter or similar tools for load testing Review regularly: Performance optimization is ongoing Conclusion MongoDB query optimization is an iterative process that requires understanding your application\u0026rsquo;s query patterns, creating appropriate indexes, and continuously monitoring performance. Start with profiling to identify bottlenecks, then optimize indexes and queries based on real usage patterns.\nRemember: Measure, optimize, test, repeat. Performance tuning is not a one-time task but an ongoing practice.\n","permalink":"https://pixcave.com/posts/mongodb-query-optimization-techniques/","summary":"\u003cp\u003eMongoDB performance optimization requires a systematic approach to identify bottlenecks, analyze query patterns, and implement effective indexing strategies. This guide covers profiling techniques, index optimization, and load testing methodologies.\u003c/p\u003e\n\u003ch2 id=\"understanding-mongodb-performance\"\u003eUnderstanding MongoDB performance\u003c/h2\u003e\n\u003cp\u003eMongoDB performance depends on several factors:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eQuery patterns\u003c/strong\u003e: How queries are structured and what operations they perform\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIndex usage\u003c/strong\u003e: Whether queries can leverage indexes effectively\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eData volume\u003c/strong\u003e: Size of collections and documents\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHardware resources\u003c/strong\u003e: CPU, memory, and disk I/O capacity\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConnection pooling\u003c/strong\u003e: How applications manage database connections\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"profiling-mongodb-queries\"\u003eProfiling MongoDB queries\u003c/h2\u003e\n\u003ch3 id=\"enable-profiling\"\u003eEnable profiling\u003c/h3\u003e\n\u003cp\u003eMongoDB\u0026rsquo;s profiler collects detailed information about query execution:\u003c/p\u003e","title":"MongoDB Query Optimization: Finding Bottlenecks and Performance Tuning"},{"content":"Optimizing React applications is crucial for better user experience. Here are proven techniques.\n1. Memoization React.memo const ExpensiveComponent = React.memo(({ data }) =\u0026gt; { return \u0026lt;div\u0026gt;{processData(data)}\u0026lt;/div\u0026gt;; }, (prevProps, nextProps) =\u0026gt; { return prevProps.data.id === nextProps.data.id; }); useMemo const expensiveValue = useMemo(() =\u0026gt; { return computeExpensiveValue(a, b); }, [a, b]); useCallback const handleClick = useCallback(() =\u0026gt; { doSomething(id); }, [id]); 2. Code Splitting React.lazy const LazyComponent = React.lazy(() =\u0026gt; import(\u0026#39;./LazyComponent\u0026#39;)); function App() { return ( \u0026lt;Suspense fallback={\u0026lt;div\u0026gt;Loading...\u0026lt;/div\u0026gt;}\u0026gt; \u0026lt;LazyComponent /\u0026gt; \u0026lt;/Suspense\u0026gt; ); } 3. Virtualization import { FixedSizeList } from \u0026#39;react-window\u0026#39;; function VirtualizedList({ items }) { return ( \u0026lt;FixedSizeList height={600} itemCount={items.length} itemSize={50} \u0026gt; {({ index, style }) =\u0026gt; ( \u0026lt;div style={style}\u0026gt;{items[index]}\u0026lt;/div\u0026gt; )} \u0026lt;/FixedSizeList\u0026gt; ); } 4. Avoid Unnecessary Renders // Bad: Creates new object on every render \u0026lt;ChildComponent config={{ theme: \u0026#39;dark\u0026#39; }} /\u0026gt; // Good: Use useMemo or constant const config = useMemo(() =\u0026gt; ({ theme: \u0026#39;dark\u0026#39; }), []); \u0026lt;ChildComponent config={config} /\u0026gt; Best Practices Memoize expensive computations Split code by routes Virtualize long lists Avoid inline functions/objects Use production builds Conclusion Optimize React apps for better performance! ⚡\n","permalink":"https://pixcave.com/posts/react-performance-optimization/","summary":"\u003cp\u003eOptimizing React applications is crucial for better user experience. Here are proven techniques.\u003c/p\u003e\n\u003ch2 id=\"1-memoization\"\u003e1. Memoization\u003c/h2\u003e\n\u003ch3 id=\"reactmemo\"\u003eReact.memo\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eExpensiveComponent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ememo\u003c/span\u003e(({ \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e }) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eprocessData\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e)}\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}, (\u003cspan style=\"color:#a6e22e\"\u003eprevProps\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enextProps\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprevProps\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003enextProps\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"usememo\"\u003euseMemo\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexpensiveValue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseMemo\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecomputeExpensiveValue\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ea\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eb\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}, [\u003cspan style=\"color:#a6e22e\"\u003ea\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eb\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"usecallback\"\u003euseCallback\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleClick\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseCallback\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edoSomething\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}, [\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-code-splitting\"\u003e2. Code Splitting\u003c/h2\u003e\n\u003ch3 id=\"reactlazy\"\u003eReact.lazy\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLazyComponent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elazy\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;./LazyComponent\u0026#39;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eSuspense\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efallback\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eLoading\u003c/span\u003e...\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;}\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eLazyComponent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/Suspense\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-virtualization\"\u003e3. Virtualization\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eFixedSizeList\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react-window\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eVirtualizedList\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e }) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eFixedSizeList\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#ae81ff\"\u003e600\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eitemCount\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eitemSize\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {({ \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e }) =\u0026gt; (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e}\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eitems\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e]}\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            )}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/FixedSizeList\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"4-avoid-unnecessary-renders\"\u003e4. Avoid Unnecessary Renders\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Creates new object on every render\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eChildComponent\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econfig\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{{ \u003cspan style=\"color:#a6e22e\"\u003etheme\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dark\u0026#39;\u003c/span\u003e }} \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use useMemo or constant\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econfig\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseMemo\u003c/span\u003e(() =\u0026gt; ({ \u003cspan style=\"color:#a6e22e\"\u003etheme\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;dark\u0026#39;\u003c/span\u003e }), []);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eChildComponent\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econfig\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003econfig\u003c/span\u003e} \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eMemoize expensive computations\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSplit code by routes\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVirtualize long lists\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid inline functions/objects\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse production builds\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eOptimize React apps for better performance! ⚡\u003c/p\u003e","title":"React Performance Optimization: Techniques and Best Practices"},{"content":"Vue 3\u0026rsquo;s Composition API provides better code organization. Here\u0026rsquo;s how to use it effectively.\nSetup import { ref, computed, watch } from \u0026#39;vue\u0026#39;; export default { setup() { const count = ref(0); const doubled = computed(() =\u0026gt; count.value * 2); watch(count, (newVal) =\u0026gt; { console.log(\u0026#39;Count changed:\u0026#39;, newVal); }); return { count, doubled }; } } Script Setup \u0026lt;script setup\u0026gt; import { ref, computed } from \u0026#39;vue\u0026#39;; const count = ref(0); const doubled = computed(() =\u0026gt; count.value * 2); function increment() { count.value++; } \u0026lt;/script\u0026gt; Composables // useCounter.js import { ref } from \u0026#39;vue\u0026#39;; export function useCounter(initialValue = 0) { const count = ref(initialValue); const increment = () =\u0026gt; count.value++; const decrement = () =\u0026gt; count.value--; return { count, increment, decrement }; } Best Practices Use composables for reusability Keep setup functions focused Use script setup syntax Organize by feature Extract complex logic Conclusion Vue 3 Composition API enables better code organization! 🎯\n","permalink":"https://pixcave.com/posts/vue-3-composition-api-guide/","summary":"\u003cp\u003eVue 3\u0026rsquo;s Composition API provides better code organization. Here\u0026rsquo;s how to use it effectively.\u003c/p\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecomputed\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ewatch\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;vue\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetup\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edoubled\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecomputed\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003enewVal\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Count changed:\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003enewVal\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edoubled\u003c/span\u003e };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"script-setup\"\u003eScript Setup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-vue\" data-lang=\"vue\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetup\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecomputed\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;vue\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edoubled\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecomputed\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"composables\"\u003eComposables\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// useCounter.js\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;vue\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseCounter\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einitialValue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eref\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einitialValue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edecrement\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edecrement\u003c/span\u003e };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse composables for reusability\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKeep setup functions focused\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse script setup syntax\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOrganize by feature\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eExtract complex logic\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eVue 3 Composition API enables better code organization! 🎯\u003c/p\u003e","title":"Vue 3 Composition API: Complete Guide and Best Practices"},{"content":"Closures are fundamental to JavaScript. Here\u0026rsquo;s how they work and when to use them.\nWhat is a Closure? A closure gives you access to an outer function\u0026rsquo;s scope from an inner function.\nfunction outer() { const name = \u0026#39;JavaScript\u0026#39;; function inner() { console.log(name); // Accesses outer scope } return inner; } const innerFunc = outer(); innerFunc(); // \u0026#34;JavaScript\u0026#34; Common Patterns Module Pattern const counter = (function() { let count = 0; return { increment: () =\u0026gt; ++count, decrement: () =\u0026gt; --count, getCount: () =\u0026gt; count }; })(); Function Factories function createMultiplier(multiplier) { return function(number) { return number * multiplier; }; } const double = createMultiplier(2); double(5); // 10 Common Pitfalls Loop with Closures // Bad: All log same value for (var i = 0; i \u0026lt; 3; i++) { setTimeout(() =\u0026gt; console.log(i), 100); // 3, 3, 3 } // Good: Use let or IIFE for (let i = 0; i \u0026lt; 3; i++) { setTimeout(() =\u0026gt; console.log(i), 100); // 0, 1, 2 } Best Practices Understand scope chain Avoid memory leaks Use closures for encapsulation Be careful in loops Use modern alternatives when possible Conclusion Master closures to write better JavaScript! 🔒\n","permalink":"https://pixcave.com/posts/javascript-closures-explained/","summary":"\u003cp\u003eClosures are fundamental to JavaScript. Here\u0026rsquo;s how they work and when to use them.\u003c/p\u003e\n\u003ch2 id=\"what-is-a-closure\"\u003eWhat is a Closure?\u003c/h2\u003e\n\u003cp\u003eA closure gives you access to an outer function\u0026rsquo;s scope from an inner function.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eouter\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;JavaScript\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einner\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// Accesses outer scope\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einner\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einnerFunc\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eouter\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003einnerFunc\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// \u0026#34;JavaScript\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-patterns\"\u003eCommon Patterns\u003c/h2\u003e\n\u003ch3 id=\"module-pattern\"\u003eModule Pattern\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecounter\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eincrement\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edecrement\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003egetCount\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e})();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"function-factories\"\u003eFunction Factories\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateMultiplier\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emultiplier\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003enumber\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003enumber\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emultiplier\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateMultiplier\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// 10\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"common-pitfalls\"\u003eCommon Pitfalls\u003c/h2\u003e\n\u003ch3 id=\"loop-with-closures\"\u003eLoop with Closures\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: All log same value\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetTimeout\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e), \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// 3, 3, 3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Use let or IIFE\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetTimeout\u003c/span\u003e(() =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e), \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// 0, 1, 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUnderstand scope chain\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid memory leaks\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse closures for encapsulation\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBe careful in loops\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse modern alternatives when possible\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMaster closures to write better JavaScript! 🔒\u003c/p\u003e","title":"JavaScript Closures Explained: Understanding Scope and Memory"},{"content":"CSS Grid and Flexbox serve different purposes. Here\u0026rsquo;s when to use each.\nFlexbox Use for One-Dimensional Layouts .navbar { display: flex; justify-content: space-between; align-items: center; } Common Use Cases Navigation bars Centering content Flexible components Equal height columns CSS Grid Use for Two-Dimensional Layouts .container { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; gap: 20px; } Common Use Cases Page layouts Complex grids Card layouts Responsive designs When to Use Both .container { display: grid; grid-template-columns: 1fr 3fr; } .sidebar { display: flex; flex-direction: column; } Best Practices Use Flexbox for components Use Grid for layouts Combine both when needed Consider browser support Test responsiveness Conclusion Choose the right tool for the job! 🎨\n","permalink":"https://pixcave.com/posts/css-grid-vs-flexbox/","summary":"\u003cp\u003eCSS Grid and Flexbox serve different purposes. Here\u0026rsquo;s when to use each.\u003c/p\u003e\n\u003ch2 id=\"flexbox\"\u003eFlexbox\u003c/h2\u003e\n\u003ch3 id=\"use-for-one-dimensional-layouts\"\u003eUse for One-Dimensional Layouts\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003enavbar\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edisplay\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eflex\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ejustify-content\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003espace-between\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ealign-items\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ecenter\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"common-use-cases\"\u003eCommon Use Cases\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNavigation bars\u003c/li\u003e\n\u003cli\u003eCentering content\u003c/li\u003e\n\u003cli\u003eFlexible components\u003c/li\u003e\n\u003cli\u003eEqual height columns\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"css-grid\"\u003eCSS Grid\u003c/h2\u003e\n\u003ch3 id=\"use-for-two-dimensional-layouts\"\u003eUse for Two-Dimensional Layouts\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003econtainer\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edisplay\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003egrid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003egrid-template-columns\u003c/span\u003e: \u003cspan style=\"color:#a6e22e\"\u003erepeat\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003efr);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003egrid-template-rows\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eauto\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003egap\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"common-use-cases-1\"\u003eCommon Use Cases\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ePage layouts\u003c/li\u003e\n\u003cli\u003eComplex grids\u003c/li\u003e\n\u003cli\u003eCard layouts\u003c/li\u003e\n\u003cli\u003eResponsive designs\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"when-to-use-both\"\u003eWhen to Use Both\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003econtainer\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edisplay\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003egrid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003egrid-template-columns\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003efr \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003efr;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebar\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edisplay\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eflex\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eflex-direction\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ecolumn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse Flexbox\u003c/strong\u003e for components\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse Grid\u003c/strong\u003e for layouts\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCombine both\u003c/strong\u003e when needed\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConsider browser support\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest responsiveness\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eChoose the right tool for the job! 🎨\u003c/p\u003e","title":"CSS Grid vs Flexbox: When to Use Which"},{"content":"Building efficient Docker images requires following best practices. Here\u0026rsquo;s how.\n1. Use Multi-Stage Builds # Build stage FROM node:18 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage FROM node:18-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules CMD [\u0026#34;node\u0026#34;, \u0026#34;dist/index.js\u0026#34;] 2. Layer Caching # Bad: Changes invalidate cache COPY . . RUN npm install # Good: Dependencies cached COPY package*.json ./ RUN npm install COPY . . 3. Use .dockerignore node_modules .git .env dist *.log 4. Minimize Layers # Bad: Multiple layers RUN apt-get update RUN apt-get install -y python RUN apt-get install -y git # Good: Single layer RUN apt-get update \u0026amp;\u0026amp; \\ apt-get install -y python git \u0026amp;\u0026amp; \\ rm -rf /var/lib/apt/lists/* 5. Use Specific Tags # Bad: Latest tag FROM node:latest # Good: Specific version FROM node:18.17.0-alpine Best Practices Multi-stage builds Optimize layer order Use .dockerignore Minimize image size Security scanning Conclusion Build efficient Docker images! 🐳\n","permalink":"https://pixcave.com/posts/docker-best-practices/","summary":"\u003cp\u003eBuilding efficient Docker images requires following best practices. Here\u0026rsquo;s how.\u003c/p\u003e\n\u003ch2 id=\"1-use-multi-stage-builds\"\u003e1. Use Multi-Stage Builds\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Build stage\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:18\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eAS\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003ebuilder\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eWORKDIR\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e/app\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e package*.json ./\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm ci\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm run build\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Production stage\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:18-alpine\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eWORKDIR\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e/app\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e --from\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebuilder /app/dist ./dist\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e --from\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebuilder /app/node_modules ./node_modules\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCMD\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;node\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dist/index.js\u0026#34;\u003c/span\u003e]\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"2-layer-caching\"\u003e2. Layer Caching\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Bad: Changes invalidate cache\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm install\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Good: Dependencies cached\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e package*.json ./\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e npm install\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCOPY\u003c/span\u003e . .\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"3-use-dockerignore\"\u003e3. Use .dockerignore\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-dockerignore\" data-lang=\"dockerignore\"\u003enode_modules\n.git\n.env\ndist\n*.log\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"4-minimize-layers\"\u003e4. Minimize Layers\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Bad: Multiple layers\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e apt-get update\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e apt-get install -y python\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e apt-get install -y git\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Good: Single layer\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eRUN\u003c/span\u003e apt-get update \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e\u003c/span\u003e    apt-get install -y python git \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e\u003c/span\u003e    rm -rf /var/lib/apt/lists/*\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"5-use-specific-tags\"\u003e5. Use Specific Tags\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Bad: Latest tag\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:latest\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e# Good: Specific version\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003enode:18.17.0-alpine\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eMulti-stage builds\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOptimize layer order\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse .dockerignore\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMinimize image size\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSecurity scanning\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eBuild efficient Docker images! 🐳\u003c/p\u003e","title":"Docker Best Practices: Building Efficient Images"},{"content":"Redis is powerful for caching. Here are effective caching strategies.\nCache-Aside Pattern async function getUser(id) { // Check cache let user = await redis.get(`user:${id}`); if (user) { return JSON.parse(user); } // Cache miss - fetch from DB user = await db.query(\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;, [id]); // Store in cache await redis.setex(`user:${id}`, 3600, JSON.stringify(user)); return user; } Write-Through Pattern async function updateUser(id, data) { // Update database const user = await db.update(\u0026#39;users\u0026#39;, id, data); // Update cache await redis.setex(`user:${id}`, 3600, JSON.stringify(user)); return user; } Cache Invalidation async function deleteUser(id) { // Delete from database await db.delete(\u0026#39;users\u0026#39;, id); // Invalidate cache await redis.del(`user:${id}`); } Best Practices Set appropriate TTL Handle cache misses Invalidate properly Monitor cache hit rate Use consistent key patterns Conclusion Implement effective Redis caching strategies! 🔴\n","permalink":"https://pixcave.com/posts/redis-caching-strategies/","summary":"\u003cp\u003eRedis is powerful for caching. Here are effective caching strategies.\u003c/p\u003e\n\u003ch2 id=\"cache-aside-pattern\"\u003eCache-Aside Pattern\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Check cache\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`user:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eparse\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Cache miss - fetch from DB\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SELECT * FROM users WHERE id = ?\u0026#39;\u003c/span\u003e, [\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Store in cache\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetex\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`user:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estringify\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"write-through-pattern\"\u003eWrite-Through Pattern\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eupdateUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Update database\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eupdate\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Update cache\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetex\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`user:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estringify\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euser\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"cache-invalidation\"\u003eCache Invalidation\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edeleteUser\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Delete from database\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#66d9ef\"\u003edelete\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Invalidate cache\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eredis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edel\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`user:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSet appropriate TTL\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle cache misses\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInvalidate properly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor cache hit rate\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse consistent key patterns\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eImplement effective Redis caching strategies! 🔴\u003c/p\u003e","title":"Redis Caching Strategies: Patterns and Best Practices"},{"content":"Optimizing MongoDB queries is essential for performance. Here\u0026rsquo;s how.\nIndexing Create Indexes // Single field index db.users.createIndex({ email: 1 }); // Compound index db.users.createIndex({ status: 1, createdAt: -1 }); // Text index db.posts.createIndex({ title: \u0026#34;text\u0026#34;, content: \u0026#34;text\u0026#34; }); Explain Queries db.users.find({ email: \u0026#34;test@example.com\u0026#34; }).explain(\u0026#34;executionStats\u0026#34;); Query Optimization Use Projection // Bad: Fetches all fields db.users.find({ status: \u0026#34;active\u0026#34; }); // Good: Only needed fields db.users.find( { status: \u0026#34;active\u0026#34; }, { name: 1, email: 1, _id: 0 } ); Limit Results db.users.find({ status: \u0026#34;active\u0026#34; }) .limit(10) .sort({ createdAt: -1 }); Best Practices Create appropriate indexes Use projection Limit result sets Avoid $regex without index Monitor slow queries Conclusion Optimize MongoDB for better performance! 🍃\n","permalink":"https://pixcave.com/posts/mongodb-query-optimization/","summary":"\u003cp\u003eOptimizing MongoDB queries is essential for performance. Here\u0026rsquo;s how.\u003c/p\u003e\n\u003ch2 id=\"indexing\"\u003eIndexing\u003c/h2\u003e\n\u003ch3 id=\"create-indexes\"\u003eCreate Indexes\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Single field index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateIndex\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Compound index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateIndex\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecreatedAt\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Text index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eposts\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateIndex\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"explain-queries\"\u003eExplain Queries\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test@example.com\u0026#34;\u003c/span\u003e }).\u003cspan style=\"color:#a6e22e\"\u003eexplain\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;executionStats\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"query-optimization\"\u003eQuery Optimization\u003c/h2\u003e\n\u003ch3 id=\"use-projection\"\u003eUse Projection\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Bad: Fetches all fields\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Good: Only needed fields\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    { \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    { \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003e_id\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"limit-results\"\u003eLimit Results\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eusers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efind\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;active\u0026#34;\u003c/span\u003e })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003elimit\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .\u003cspan style=\"color:#a6e22e\"\u003esort\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ecreatedAt\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eCreate appropriate indexes\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse projection\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLimit result sets\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid $regex without index\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor slow queries\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eOptimize MongoDB for better performance! 🍃\u003c/p\u003e","title":"MongoDB Query Optimization: Indexing and Performance Tips"},{"content":"Elasticsearch is powerful for search. Here\u0026rsquo;s how to get started.\nBasic Operations Create Index await client.indices.create({ index: \u0026#39;users\u0026#39;, body: { mappings: { properties: { name: { type: \u0026#39;text\u0026#39; }, email: { type: \u0026#39;keyword\u0026#39; }, age: { type: \u0026#39;integer\u0026#39; } } } } }); Index Document await client.index({ index: \u0026#39;users\u0026#39;, id: \u0026#39;1\u0026#39;, body: { name: \u0026#39;John Doe\u0026#39;, email: \u0026#39;john@example.com\u0026#39;, age: 30 } }); Search const result = await client.search({ index: \u0026#39;users\u0026#39;, body: { query: { match: { name: \u0026#39;John\u0026#39; } } } }); Best Practices Design mappings carefully Use appropriate analyzers Optimize queries Monitor cluster health Backup regularly Conclusion Master Elasticsearch for powerful search! 🔍\n","permalink":"https://pixcave.com/posts/elasticsearch-basics/","summary":"\u003cp\u003eElasticsearch is powerful for search. Here\u0026rsquo;s how to get started.\u003c/p\u003e\n\u003ch2 id=\"basic-operations\"\u003eBasic Operations\u003c/h2\u003e\n\u003ch3 id=\"create-index\"\u003eCreate Index\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindices\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emappings\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eproperties\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;text\u0026#39;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;keyword\u0026#39;\u003c/span\u003e },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eage\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;integer\u0026#39;\u003c/span\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"index-document\"\u003eIndex Document\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;1\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;John Doe\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eemail\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;john@example.com\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eage\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e30\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"search\"\u003eSearch\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esearch\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;users\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003equery\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003ematch\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;John\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eDesign mappings carefully\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse appropriate analyzers\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOptimize queries\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor cluster health\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBackup regularly\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMaster Elasticsearch for powerful search! 🔍\u003c/p\u003e","title":"Elasticsearch Basics: Getting Started with Search"},{"content":"RabbitMQ enables reliable message queuing. Here\u0026rsquo;s how to use it effectively.\nBasic Setup Producer const amqp = require(\u0026#39;amqplib\u0026#39;); async function sendMessage() { const connection = await amqp.connect(\u0026#39;amqp://localhost\u0026#39;); const channel = await connection.createChannel(); const queue = \u0026#39;tasks\u0026#39;; const message = \u0026#39;Hello RabbitMQ!\u0026#39;; await channel.assertQueue(queue, { durable: true }); channel.sendToQueue(queue, Buffer.from(message), { persistent: true }); console.log(\u0026#34;Sent:\u0026#34;, message); await channel.close(); await connection.close(); } Consumer async function receiveMessage() { const connection = await amqp.connect(\u0026#39;amqp://localhost\u0026#39;); const channel = await connection.createChannel(); const queue = \u0026#39;tasks\u0026#39;; await channel.assertQueue(queue, { durable: true }); channel.consume(queue, (msg) =\u0026gt; { if (msg) { console.log(\u0026#34;Received:\u0026#34;, msg.content.toString()); channel.ack(msg); } }); } Patterns Work Queues // Distribute tasks among workers channel.prefetch(1); // Fair dispatch Pub/Sub // Exchange for broadcasting await channel.assertExchange(\u0026#39;logs\u0026#39;, \u0026#39;fanout\u0026#39;, { durable: false }); channel.publish(\u0026#39;logs\u0026#39;, \u0026#39;\u0026#39;, Buffer.from(message)); Best Practices Use durable queues Acknowledge messages Handle errors Monitor queues Use exchanges for routing Conclusion Implement reliable message queuing with RabbitMQ! 🐰\n","permalink":"https://pixcave.com/posts/rabbitmq-message-queues/","summary":"\u003cp\u003eRabbitMQ enables reliable message queuing. Here\u0026rsquo;s how to use it effectively.\u003c/p\u003e\n\u003ch2 id=\"basic-setup\"\u003eBasic Setup\u003c/h2\u003e\n\u003ch3 id=\"producer\"\u003eProducer\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eamqp\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;amqplib\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esendMessage\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econnection\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eamqp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econnect\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;amqp://localhost\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econnection\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateChannel\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tasks\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Hello RabbitMQ!\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eassertQueue\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003edurable\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esendToQueue\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eBuffer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e), {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003epersistent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Sent:\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclose\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econnection\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclose\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"consumer\"\u003eConsumer\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereceiveMessage\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econnection\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eamqp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econnect\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;amqp://localhost\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econnection\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateChannel\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tasks\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eassertQueue\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003edurable\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econsume\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003equeue\u003c/span\u003e, (\u003cspan style=\"color:#a6e22e\"\u003emsg\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003emsg\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Received:\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003emsg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eack\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emsg\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"patterns\"\u003ePatterns\u003c/h2\u003e\n\u003ch3 id=\"work-queues\"\u003eWork Queues\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Distribute tasks among workers\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprefetch\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// Fair dispatch\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"pubsub\"\u003ePub/Sub\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Exchange for broadcasting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eassertExchange\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;logs\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;fanout\u0026#39;\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003edurable\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003echannel\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epublish\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;logs\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eBuffer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emessage\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse durable queues\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAcknowledge messages\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle errors\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor queues\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse exchanges for routing\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eImplement reliable message queuing with RabbitMQ! 🐰\u003c/p\u003e","title":"RabbitMQ Message Queues: Patterns and Implementation"},{"content":"PostgreSQL performance tuning requires understanding configuration and queries. Here\u0026rsquo;s a guide.\nConfiguration Tuning postgresql.conf # Memory settings shared_buffers = 256MB effective_cache_size = 1GB work_mem = 16MB # Connection settings max_connections = 100 # Query planner random_page_cost = 1.1 Query Optimization Use EXPLAIN ANALYZE EXPLAIN ANALYZE SELECT * FROM users WHERE email = \u0026#39;test@example.com\u0026#39;; Indexing -- B-tree index CREATE INDEX idx_user_email ON users(email); -- Partial index CREATE INDEX idx_active_users ON users(email) WHERE status = \u0026#39;active\u0026#39;; -- Composite index CREATE INDEX idx_user_status_created ON users(status, created_at); Best Practices Analyze query plans Create appropriate indexes Use connection pooling Monitor slow queries Vacuum regularly Conclusion Tune PostgreSQL for optimal performance! 🐘\n","permalink":"https://pixcave.com/posts/postgresql-performance-tuning/","summary":"\u003cp\u003ePostgreSQL performance tuning requires understanding configuration and queries. Here\u0026rsquo;s a guide.\u003c/p\u003e\n\u003ch2 id=\"configuration-tuning\"\u003eConfiguration Tuning\u003c/h2\u003e\n\u003ch3 id=\"postgresqlconf\"\u003epostgresql.conf\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003e# Memory settings\nshared_buffers = 256MB\neffective_cache_size = 1GB\nwork_mem = 16MB\n\n# Connection settings\nmax_connections = 100\n\n# Query planner\nrandom_page_cost = 1.1\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"query-optimization\"\u003eQuery Optimization\u003c/h2\u003e\n\u003ch3 id=\"use-explain-analyze\"\u003eUse EXPLAIN ANALYZE\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eEXPLAIN\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eANALYZE\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eSELECT\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eFROM\u003c/span\u003e users \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e email \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;test@example.com\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"indexing\"\u003eIndexing\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- B-tree index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_user_email \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e users(email);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Partial index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_active_users \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e users(email) \u003cspan style=\"color:#66d9ef\"\u003eWHERE\u003c/span\u003e status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;active\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e-- Composite index\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eCREATE\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eINDEX\u003c/span\u003e idx_user_status_created \u003cspan style=\"color:#66d9ef\"\u003eON\u003c/span\u003e users(status, created_at);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eAnalyze query plans\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCreate appropriate indexes\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse connection pooling\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor slow queries\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVacuum regularly\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eTune PostgreSQL for optimal performance! 🐘\u003c/p\u003e","title":"PostgreSQL Performance Tuning: Optimization Guide"},{"content":"Understanding Python\u0026rsquo;s asyncio architecture is crucial for writing efficient asynchronous code. Here\u0026rsquo;s a comprehensive guide.\nEvent Loop The event loop is the core of asyncio. It manages and distributes the execution of different tasks.\nimport asyncio async def main(): print(\u0026#34;Hello\u0026#34;) await asyncio.sleep(1) print(\u0026#34;World\u0026#34;) # Event loop runs the coroutine asyncio.run(main()) Coroutines Coroutines are functions defined with async def. They can be paused and resumed.\nasync def fetch_data(): await asyncio.sleep(1) return \u0026#34;data\u0026#34; # Coroutine object coro = fetch_data() Tasks Tasks wrap coroutines and schedule them on the event loop.\nasync def main(): task1 = asyncio.create_task(fetch_data()) task2 = asyncio.create_task(fetch_data()) result1 = await task1 result2 = await task2 return [result1, result2] Futures Futures represent the result of an asynchronous operation.\nasync def main(): loop = asyncio.get_event_loop() future = loop.create_future() async def set_result(): await asyncio.sleep(1) future.set_result(\u0026#34;Done\u0026#34;) asyncio.create_task(set_result()) result = await future return result Best Practices Use asyncio.run() for entry points Create tasks for concurrent operations Handle exceptions properly Use async context managers Avoid blocking operations Conclusion Master asyncio architecture for efficient Python async programming! 🐍\n","permalink":"https://pixcave.com/posts/python-asyncio-architecture/","summary":"\u003cp\u003eUnderstanding Python\u0026rsquo;s asyncio architecture is crucial for writing efficient asynchronous code. Here\u0026rsquo;s a comprehensive guide.\u003c/p\u003e\n\u003ch2 id=\"event-loop\"\u003eEvent Loop\u003c/h2\u003e\n\u003cp\u003eThe event loop is the core of asyncio. It manages and distributes the execution of different tasks.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e asyncio\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e asyncio\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;World\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Event loop runs the coroutine\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003easyncio\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erun(main())\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"coroutines\"\u003eCoroutines\u003c/h2\u003e\n\u003cp\u003eCoroutines are functions defined with \u003ccode\u003easync def\u003c/code\u003e. They can be paused and resumed.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efetch_data\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e asyncio\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;data\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Coroutine object\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecoro \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fetch_data()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"tasks\"\u003eTasks\u003c/h2\u003e\n\u003cp\u003eTasks wrap coroutines and schedule them on the event loop.\u003c/p\u003e","title":"Python Asyncio Architecture: Event Loops, Tasks, and Futures Explained"},{"content":"Learn how to build a simple blog application using Python and Flask.\nSetup from flask import Flask, render_template, request, redirect, url_for app = Flask(__name__) # Simple in-memory storage posts = [] Routes @app.route(\u0026#39;/\u0026#39;) def index(): return render_template(\u0026#39;index.html\u0026#39;, posts=posts) @app.route(\u0026#39;/post\u0026#39;, methods=[\u0026#39;GET\u0026#39;, \u0026#39;POST\u0026#39;]) def create_post(): if request.method == \u0026#39;POST\u0026#39;: title = request.form[\u0026#39;title\u0026#39;] content = request.form[\u0026#39;content\u0026#39;] posts.append({\u0026#39;title\u0026#39;: title, \u0026#39;content\u0026#39;: content}) return redirect(url_for(\u0026#39;index\u0026#39;)) return render_template(\u0026#39;create_post.html\u0026#39;) Templates \u0026lt;!-- index.html --\u0026gt; {% for post in posts %} \u0026lt;article\u0026gt; \u0026lt;h2\u0026gt;{{ post.title }}\u0026lt;/h2\u0026gt; \u0026lt;p\u0026gt;{{ post.content }}\u0026lt;/p\u0026gt; \u0026lt;/article\u0026gt; {% endfor %} Running flask run Conclusion Build your first Flask blog application! 🚀\n","permalink":"https://pixcave.com/posts/python-flask-mini-blog/","summary":"\u003cp\u003eLearn how to build a simple blog application using Python and Flask.\u003c/p\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e flask \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Flask, render_template, request, redirect, url_for\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Flask(__name__)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Simple in-memory storage\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eposts \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"routes\"\u003eRoutes\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@app.route\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e render_template(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;index.html\u0026#39;\u003c/span\u003e, posts\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eposts)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@app.route\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/post\u0026#39;\u003c/span\u003e, methods\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GET\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;POST\u0026#39;\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate_post\u003c/span\u003e():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e request\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emethod \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;POST\u0026#39;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        title \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e request\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eform[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;title\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        content \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e request\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eform[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;content\u0026#39;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        posts\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend({\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;title\u0026#39;\u003c/span\u003e: title, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;content\u0026#39;\u003c/span\u003e: content})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e redirect(url_for(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;index\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e render_template(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;create_post.html\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"templates\"\u003eTemplates\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- index.html --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{% for post in posts %}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003earticle\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eh2\u003c/span\u003e\u0026gt;{{ post.title }}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eh2\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;{{ post.content }}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003earticle\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{% endfor %}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"running\"\u003eRunning\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eflask run\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eBuild your first Flask blog application! 🚀\u003c/p\u003e","title":"Building a Mini Blog with Python and Flask"},{"content":"Ownership is Rust\u0026rsquo;s unique feature that ensures memory safety without garbage collection.\nOwnership Rules Each value has a single owner Only one owner at a time When owner goes out of scope, value is dropped let s = String::from(\u0026#34;hello\u0026#34;); // s owns the string Moving let s1 = String::from(\u0026#34;hello\u0026#34;); let s2 = s1; // s1 is moved to s2 // s1 is no longer valid Borrowing fn calculate_length(s: \u0026amp;String) -\u0026gt; usize { s.len() } let s = String::from(\u0026#34;hello\u0026#34;); let len = calculate_length(\u0026amp;s); // Borrowing Mutable References fn change(s: \u0026amp;mut String) { s.push_str(\u0026#34;, world\u0026#34;); } let mut s = String::from(\u0026#34;hello\u0026#34;); change(\u0026amp;mut s); Best Practices Use references when possible Understand ownership rules Avoid unnecessary moves Use clone() sparingly Leverage the borrow checker Conclusion Master Rust ownership for memory-safe systems programming! 🦀\n","permalink":"https://pixcave.com/posts/rust-ownership-explained/","summary":"\u003cp\u003eOwnership is Rust\u0026rsquo;s unique feature that ensures memory safety without garbage collection.\u003c/p\u003e\n\u003ch2 id=\"ownership-rules\"\u003eOwnership Rules\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eEach value has a single owner\u003c/li\u003e\n\u003cli\u003eOnly one owner at a time\u003c/li\u003e\n\u003cli\u003eWhen owner goes out of scope, value is dropped\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String::from(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// s owns the string\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"moving\"\u003eMoving\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String::from(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s1; \u003cspan style=\"color:#75715e\"\u003e// s1 is moved to s2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// s1 is no longer valid\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"borrowing\"\u003eBorrowing\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecalculate_length\u003c/span\u003e(s: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003eString) -\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003eusize\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    s.len()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e s \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String::from(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e calculate_length(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003es); \u003cspan style=\"color:#75715e\"\u003e// Borrowing\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"mutable-references\"\u003eMutable References\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echange\u003c/span\u003e(s: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003emut\u003c/span\u003e String) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    s.push_str(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;, world\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e s \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String::from(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echange(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003emut\u003c/span\u003e s);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse references\u003c/strong\u003e when possible\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUnderstand ownership\u003c/strong\u003e rules\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAvoid unnecessary moves\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003eclone()\u003c/code\u003e\u003c/strong\u003e sparingly\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLeverage the borrow checker\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMaster Rust ownership for memory-safe systems programming! 🦀\u003c/p\u003e","title":"Rust Ownership: Understanding Memory Safety"},{"content":"Rust\u0026rsquo;s error handling is elegant and type-safe. Here\u0026rsquo;s how to use it effectively.\nOption Type fn find_user(id: u32) -\u0026gt; Option\u0026lt;String\u0026gt; { if id \u0026gt; 0 { Some(format!(\u0026#34;User {}\u0026#34;, id)) } else { None } } match find_user(1) { Some(name) =\u0026gt; println!(\u0026#34;Found: {}\u0026#34;, name), None =\u0026gt; println!(\u0026#34;Not found\u0026#34;), } Result Type use std::fs::File; fn read_file(path: \u0026amp;str) -\u0026gt; Result\u0026lt;String, std::io::Error\u0026gt; { std::fs::read_to_string(path) } match read_file(\u0026#34;data.txt\u0026#34;) { Ok(content) =\u0026gt; println!(\u0026#34;Content: {}\u0026#34;, content), Err(e) =\u0026gt; println!(\u0026#34;Error: {}\u0026#34;, e), } Error Propagation fn read_config() -\u0026gt; Result\u0026lt;String, std::io::Error\u0026gt; { let content = std::fs::read_to_string(\u0026#34;config.txt\u0026#34;)?; Ok(content) } Custom Errors use std::fmt; #[derive(Debug)] struct CustomError { message: String, } impl fmt::Display for CustomError { fn fmt(\u0026amp;self, f: \u0026amp;mut fmt::Formatter) -\u0026gt; fmt::Result { write!(f, \u0026#34;{}\u0026#34;, self.message) } } Best Practices Use Result for recoverable errors Use Option for optional values Propagate errors with ? Create custom errors when needed Handle errors explicitly Conclusion Handle errors elegantly in Rust! 🦀\n","permalink":"https://pixcave.com/posts/rust-error-handling-guide/","summary":"\u003cp\u003eRust\u0026rsquo;s error handling is elegant and type-safe. Here\u0026rsquo;s how to use it effectively.\u003c/p\u003e\n\u003ch2 id=\"option-type\"\u003eOption Type\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efind_user\u003c/span\u003e(id: \u003cspan style=\"color:#66d9ef\"\u003eu32\u003c/span\u003e) -\u0026gt; Option\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e id \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Some(\u003cspan style=\"color:#a6e22e\"\u003eformat!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;User \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, id))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        None\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ematch\u003c/span\u003e find_user(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Some(name) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Found: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, name),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    None \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Not found\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"result-type\"\u003eResult Type\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e std::fs::File;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eread_file\u003c/span\u003e(path: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003estr\u003c/span\u003e) -\u0026gt; Result\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString, std::io::Error\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    std::fs::read_to_string(path)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ematch\u003c/span\u003e read_file(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;data.txt\u0026#34;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Ok(content) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Content: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, content),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Err(e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprintln!\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Error: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"error-propagation\"\u003eError Propagation\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eread_config\u003c/span\u003e() -\u0026gt; Result\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eString, std::io::Error\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e content \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e std::fs::read_to_string(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;config.txt\u0026#34;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Ok(content)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"custom-errors\"\u003eCustom Errors\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e std::fmt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[derive(Debug)]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCustomError\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    message: String,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimpl\u003c/span\u003e fmt::Display \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e CustomError {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efmt\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eself, f: \u003cspan style=\"color:#66d9ef\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003emut\u003c/span\u003e fmt::Formatter) -\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003efmt\u003c/span\u003e::Result {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewrite!\u003c/span\u003e(f, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;{}\u0026#34;\u003c/span\u003e, self.message)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003eResult\u003c/code\u003e\u003c/strong\u003e for recoverable errors\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse \u003ccode\u003eOption\u003c/code\u003e\u003c/strong\u003e for optional values\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePropagate errors\u003c/strong\u003e with \u003ccode\u003e?\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCreate custom errors\u003c/strong\u003e when needed\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle errors\u003c/strong\u003e explicitly\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eHandle errors elegantly in Rust! 🦀\u003c/p\u003e","title":"Rust Error Handling: Complete Guide with Result and Option"},{"content":"Using SQLAlchemy with async Python requires understanding async patterns. Here\u0026rsquo;s how.\nSetup from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker engine = create_async_engine(\u0026#34;postgresql+asyncpg://user:pass@localhost/db\u0026#34;) AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) Async Models from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Base = declarative_base() class User(Base): __tablename__ = \u0026#34;users\u0026#34; id = Column(Integer, primary_key=True) name = Column(String) Async Operations async def create_user(name: str): async with AsyncSessionLocal() as session: user = User(name=name) session.add(user) await session.commit() return user async def get_user(user_id: int): async with AsyncSessionLocal() as session: result = await session.get(User, user_id) return result Best Practices Use async context managers Commit transactions explicitly Handle exceptions properly Use connection pooling Close sessions correctly Conclusion Build efficient async database applications with SQLAlchemy! 🐍\n","permalink":"https://pixcave.com/posts/python-sqlalchemy-async-guide/","summary":"\u003cp\u003eUsing SQLAlchemy with async Python requires understanding async patterns. Here\u0026rsquo;s how.\u003c/p\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e sqlalchemy.ext.asyncio \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e create_async_engine, AsyncSession\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e sqlalchemy.orm \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e sessionmaker\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eengine \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e create_async_engine(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;postgresql+asyncpg://user:pass@localhost/db\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAsyncSessionLocal \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sessionmaker(engine, class_\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eAsyncSession, expire_on_commit\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eFalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"async-models\"\u003eAsync Models\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e sqlalchemy.ext.declarative \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e declarative_base\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e sqlalchemy \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Column, Integer, String\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBase \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e declarative_base()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e(Base):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    __tablename__ \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;users\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    id \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Column(Integer, primary_key\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eTrue\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Column(String)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"async-operations\"\u003eAsync Operations\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate_user\u003c/span\u003e(name: str):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e AsyncSessionLocal() \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e session:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e User(name\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ename)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        session\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eadd(user)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e session\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecommit()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e user\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eget_user\u003c/span\u003e(user_id: int):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ewith\u003c/span\u003e AsyncSessionLocal() \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e session:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e session\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eget(User, user_id)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e result\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse async context managers\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCommit transactions\u003c/strong\u003e explicitly\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle exceptions\u003c/strong\u003e properly\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse connection pooling\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eClose sessions\u003c/strong\u003e correctly\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eBuild efficient async database applications with SQLAlchemy! 🐍\u003c/p\u003e","title":"Async SQLAlchemy: Best Practices for Async Python Applications"},{"content":"Rust WebAssembly can significantly improve React application performance. Here\u0026rsquo;s how to integrate it.\nSetup cargo install wasm-pack wasm-pack build --target web Rust Code use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn add(a: i32, b: i32) -\u0026gt; i32 { a + b } React Integration import init, { add } from \u0026#39;./pkg/rust_wasm.js\u0026#39;; async function loadWasm() { await init(); console.log(add(2, 3)); // 5 } Performance Benefits Faster computation for heavy operations Memory efficient Type safe Near-native performance Best Practices Use for CPU-intensive tasks Minimize data transfer Profile performance Handle errors properly Bundle efficiently Conclusion Boost React performance with Rust WebAssembly! ⚡\n","permalink":"https://pixcave.com/posts/rust-webassembly-react/","summary":"\u003cp\u003eRust WebAssembly can significantly improve React application performance. Here\u0026rsquo;s how to integrate it.\u003c/p\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecargo install wasm-pack\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewasm-pack build --target web\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"rust-code\"\u003eRust Code\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e wasm_bindgen::prelude::\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[wasm_bindgen]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epub\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(a: \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e, b: \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e) -\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003ei32\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    a \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e b\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"react-integration\"\u003eReact Integration\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e, { \u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;./pkg/rust_wasm.js\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eloadWasm\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eadd\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e)); \u003cspan style=\"color:#75715e\"\u003e// 5\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"performance-benefits\"\u003ePerformance Benefits\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFaster computation\u003c/strong\u003e for heavy operations\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory efficient\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eType safe\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNear-native performance\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse for CPU-intensive tasks\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMinimize data transfer\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProfile performance\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle errors\u003c/strong\u003e properly\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBundle efficiently\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eBoost React performance with Rust WebAssembly! ⚡\u003c/p\u003e","title":"Using Rust WebAssembly in React: Performance Optimization"},{"content":"Pandas provides powerful tools for joining DataFrames. Here\u0026rsquo;s a comprehensive guide.\nMerge Types Inner Join import pandas as pd df1 = pd.DataFrame({\u0026#39;key\u0026#39;: [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;], \u0026#39;value1\u0026#39;: [1, 2]}) df2 = pd.DataFrame({\u0026#39;key\u0026#39;: [\u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;], \u0026#39;value2\u0026#39;: [3, 4]}) result = pd.merge(df1, df2, on=\u0026#39;key\u0026#39;, how=\u0026#39;inner\u0026#39;) Left Join result = pd.merge(df1, df2, on=\u0026#39;key\u0026#39;, how=\u0026#39;left\u0026#39;) Right Join result = pd.merge(df1, df2, on=\u0026#39;key\u0026#39;, how=\u0026#39;right\u0026#39;) Outer Join result = pd.merge(df1, df2, on=\u0026#39;key\u0026#39;, how=\u0026#39;outer\u0026#39;) Multiple Keys result = pd.merge(df1, df2, on=[\u0026#39;key1\u0026#39;, \u0026#39;key2\u0026#39;]) Best Practices Choose the right join type Handle missing values Use appropriate keys Check for duplicates Optimize for large datasets Conclusion Master Pandas joins for efficient data manipulation! 📊\n","permalink":"https://pixcave.com/posts/python-pandas-joins-guide/","summary":"\u003cp\u003ePandas provides powerful tools for joining DataFrames. Here\u0026rsquo;s a comprehensive guide.\u003c/p\u003e\n\u003ch2 id=\"merge-types\"\u003eMerge Types\u003c/h2\u003e\n\u003ch3 id=\"inner-join\"\u003eInner Join\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e pandas \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e pd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eDataFrame({\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e], \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;value1\u0026#39;\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eDataFrame({\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;C\u0026#39;\u003c/span\u003e], \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;value2\u0026#39;\u003c/span\u003e: [\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e]})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emerge(df1, df2, on\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e, how\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;inner\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"left-join\"\u003eLeft Join\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emerge(df1, df2, on\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e, how\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;left\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"right-join\"\u003eRight Join\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emerge(df1, df2, on\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e, how\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;right\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"outer-join\"\u003eOuter Join\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emerge(df1, df2, on\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key\u0026#39;\u003c/span\u003e, how\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;outer\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"multiple-keys\"\u003eMultiple Keys\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pd\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emerge(df1, df2, on\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key1\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;key2\u0026#39;\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eChoose the right join type\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle missing values\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse appropriate keys\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCheck for duplicates\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOptimize for large datasets\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMaster Pandas joins for efficient data manipulation! 📊\u003c/p\u003e","title":"Pandas Joins: Complete Guide to Merging DataFrames"},{"content":"Migrating from Python 2 to Python 3 requires careful planning. Here\u0026rsquo;s a step-by-step guide.\nKey Differences Print Statement # Python 2 print \u0026#34;Hello\u0026#34; # Python 3 print(\u0026#34;Hello\u0026#34;) Division # Python 2 5 / 2 # 2 # Python 3 5 / 2 # 2.5 5 // 2 # 2 Unicode # Python 2 s = u\u0026#34;Hello\u0026#34; # Python 3 s = \u0026#34;Hello\u0026#34; # Unicode by default Migration Tools # 2to3 tool 2to3 -w script.py # Modernize python-modernize script.py Best Practices Test thoroughly Update dependencies Use type hints Handle bytes/strings Update string formatting Conclusion Migrate to Python 3 for modern Python development! 🐍\n","permalink":"https://pixcave.com/posts/python-migration-2-to-3/","summary":"\u003cp\u003eMigrating from Python 2 to Python 3 requires careful planning. Here\u0026rsquo;s a step-by-step guide.\u003c/p\u003e\n\u003ch2 id=\"key-differences\"\u003eKey Differences\u003c/h2\u003e\n\u003ch3 id=\"print-statement\"\u003ePrint Statement\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprint \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprint(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"division\"\u003eDivision\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 2.5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"unicode\"\u003eUnicode\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 2\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003es \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eu\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Python 3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003es \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello\u0026#34;\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# Unicode by default\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"migration-tools\"\u003eMigration Tools\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 2to3 tool\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e2to3 -w script.py\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Modernize\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython-modernize script.py\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eTest thoroughly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUpdate dependencies\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse type hints\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle bytes/strings\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUpdate string formatting\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eMigrate to Python 3 for modern Python development! 🐍\u003c/p\u003e","title":"Migrating from Python 2 to Python 3: Complete Guide"},{"content":"Axum is a modern web framework for Rust. Here\u0026rsquo;s how to build your first API.\nSetup [dependencies] axum = \u0026#34;0.7\u0026#34; tokio = { version = \u0026#34;1\u0026#34;, features = [\u0026#34;full\u0026#34;] } serde = { version = \u0026#34;1.0\u0026#34;, features = [\u0026#34;derive\u0026#34;] } Basic Server use axum::{Router, routing::get, Json}; #[tokio::main] async fn main() { let app = Router::new() .route(\u0026#34;/\u0026#34;, get(handler)); axum::Server::bind(\u0026amp;\u0026#34;0.0.0.0:3000\u0026#34;.parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); } async fn handler() -\u0026gt; Json\u0026lt;serde_json::Value\u0026gt; { Json(serde_json::json!({\u0026#34;message\u0026#34;: \u0026#34;Hello, World!\u0026#34;})) } Routes let app = Router::new() .route(\u0026#34;/users\u0026#34;, get(get_users)) .route(\u0026#34;/users/:id\u0026#34;, get(get_user)); JSON Handling use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct User { id: u32, name: String, } async fn create_user(Json(user): Json\u0026lt;User\u0026gt;) -\u0026gt; Json\u0026lt;User\u0026gt; { Json(user) } Best Practices Use type-safe routing Handle errors properly Use middleware Test endpoints Document APIs Conclusion Build fast and safe APIs with Rust and Axum! 🦀\n","permalink":"https://pixcave.com/posts/rust-http-api-axum/","summary":"\u003cp\u003eAxum is a modern web framework for Rust. Here\u0026rsquo;s how to build your first API.\u003c/p\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-toml\" data-lang=\"toml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[\u003cspan style=\"color:#a6e22e\"\u003edependencies\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eaxum\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0.7\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003etokio\u003c/span\u003e = { \u003cspan style=\"color:#a6e22e\"\u003eversion\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003efeatures\u003c/span\u003e = [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;full\u0026#34;\u003c/span\u003e] }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eserde\u003c/span\u003e = { \u003cspan style=\"color:#a6e22e\"\u003eversion\u003c/span\u003e = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1.0\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003efeatures\u003c/span\u003e = [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;derive\u0026#34;\u003c/span\u003e] }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"basic-server\"\u003eBasic Server\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e axum::{Router, routing::get, Json};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[tokio::main]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e app \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Router::new()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .route(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e, get(handler));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    axum::Server::bind(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;0.0.0.0:3000\u0026#34;\u003c/span\u003e.parse().unwrap())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .serve(app.into_make_service())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .\u003cspan style=\"color:#66d9ef\"\u003eawait\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        .unwrap();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandler\u003c/span\u003e() -\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eJson\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eserde_json::Value\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Json(serde_json::\u003cspan style=\"color:#a6e22e\"\u003ejson!\u003c/span\u003e({\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hello, World!\u0026#34;\u003c/span\u003e}))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"routes\"\u003eRoutes\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e app \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Router::new()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .route(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users\u0026#34;\u003c/span\u003e, get(get_users))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    .route(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/users/:id\u0026#34;\u003c/span\u003e, get(get_user));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"json-handling\"\u003eJSON Handling\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-rust\" data-lang=\"rust\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e serde::{Deserialize, Serialize};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#[derive(Serialize, Deserialize)]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUser\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    id: \u003cspan style=\"color:#66d9ef\"\u003eu32\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    name: String,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003easync\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate_user\u003c/span\u003e(Json(user): \u003cspan style=\"color:#a6e22e\"\u003eJson\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e) -\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eJson\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUser\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Json(user)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eUse type-safe routing\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eHandle errors properly\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse middleware\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTest endpoints\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDocument APIs\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eBuild fast and safe APIs with Rust and Axum! 🦀\u003c/p\u003e","title":"Building Your First Rust HTTP API with Axum"},{"content":"Optimizing Spark jobs is crucial for performance. Here\u0026rsquo;s how to use partitioning and bucketing effectively.\nPartitioning from pyspark.sql import SparkSession spark = SparkSession.builder.appName(\u0026#34;Optimization\u0026#34;).getOrCreate() # Repartition df = df.repartition(10, \u0026#34;column_name\u0026#34;) # Coalesce df = df.coalesce(5) Bucketing df.write \\ .bucketBy(10, \u0026#34;bucket_column\u0026#34;) \\ .sortBy(\u0026#34;sort_column\u0026#34;) \\ .saveAsTable(\u0026#34;bucketed_table\u0026#34;) Broadcast Joins from pyspark.sql.functions import broadcast result = large_df.join(broadcast(small_df), \u0026#34;key\u0026#34;) Caching df.cache() df.persist() Best Practices Partition appropriately Use bucketing for joins Broadcast small tables Cache frequently used data Monitor performance Conclusion Optimize Spark jobs for better performance! ⚡\n","permalink":"https://pixcave.com/posts/python-spark-optimization/","summary":"\u003cp\u003eOptimizing Spark jobs is crucial for performance. Here\u0026rsquo;s how to use partitioning and bucketing effectively.\u003c/p\u003e\n\u003ch2 id=\"partitioning\"\u003ePartitioning\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e pyspark.sql \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e SparkSession\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003espark \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e SparkSession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ebuilder\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappName(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Optimization\u0026#34;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egetOrCreate()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Repartition\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e df\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erepartition(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;column_name\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Coalesce\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e df\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecoalesce(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"bucketing\"\u003eBucketing\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite \\\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ebucketBy(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;bucket_column\u0026#34;\u003c/span\u003e) \\\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esortBy(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sort_column\u0026#34;\u003c/span\u003e) \\\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esaveAsTable(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;bucketed_table\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"broadcast-joins\"\u003eBroadcast Joins\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e pyspark.sql.functions \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e broadcast\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eresult \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e large_df\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(broadcast(small_df), \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;key\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"caching\"\u003eCaching\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecache()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edf\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epersist()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"best-practices\"\u003eBest Practices\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003ePartition appropriately\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eUse bucketing\u003c/strong\u003e for joins\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBroadcast small tables\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCache frequently used data\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMonitor performance\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"conclusion\"\u003eConclusion\u003c/h2\u003e\n\u003cp\u003eOptimize Spark jobs for better performance! ⚡\u003c/p\u003e","title":"Apache Spark Optimization: Partitioning and Bucketing Guide"},{"content":"A collection of carefully selected learning resources, tools, and references to help you become a better developer. From documentation to tutorials, frameworks to design systems.\n","permalink":"https://pixcave.com/resources/","summary":"Curated learning resources and tools for developers","title":"Resources"},{"content":"","permalink":"https://pixcave.com/sitemap/","summary":"","title":"Sitemap"},{"content":"Explore our content journey through time. See how our knowledge base has grown and find articles from any point in our publishing history.\n","permalink":"https://pixcave.com/timeline/","summary":"A chronological journey through all our articles","title":"Timeline"},{"content":"Browse all articles organized by topics and technologies. From frontend frameworks to backend systems, DevOps to design patterns - find the content that matters to you.\n","permalink":"https://pixcave.com/topics/","summary":"Explore articles by technology and theme","title":"Topics"}]