- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Load Balancers Explained: Spreading Traffic Without Losing Sessions
About Post
You add a second server so the app can handle more traffic. You put a load balancer in front. Everything looks great, until users start getting logged out at random, file uploads vanish half the time, and the nightly report emails go out twice.
Nothing is broken, exactly. Your app just quietly assumed it was the only server in the world, and now it isn't. Load balancers are simple in principle, and most of the trouble comes from what they change about your application. Let's cover both.
What a load balancer does
Think of the host at the door of a busy restaurant. Guests don't pick their own table; the host looks at which waiters are free, skips the section that's closed, and seats people where they'll be served fastest. If a waiter goes home sick, the host stops sending guests to that section.
A load balancer is that host. It accepts every incoming request, picks a healthy backend server, and forwards the request there. That gives you three things:
- Capacity: more servers, more requests handled.
- Availability: one server dies, the others keep serving.
- Easier deploys: take servers out of rotation one at a time, update, put them back.
Layer 4 vs layer 7
The layers come from the OSI model, and the difference is how much of the request the load balancer looks at.
| Layer 4 (transport) | Layer 7 (application) | |
|---|---|---|
| Sees | IP addresses and ports (TCP/UDP) | The full HTTP request: path, headers, cookies |
| Can route by | Connection only | URL path, host name, header, cookie |
| TLS | Usually passes it through | Usually terminates it (holds the certificate) |
| Speed | Very fast, very little work per packet | A bit more work per request, far more flexible |
| Examples | AWS Network Load Balancer, HAProxy in TCP mode | AWS Application Load Balancer, Nginx, HAProxy in HTTP mode |
For a typical web app or API, layer 7 is what you want. Sending /api/* to one group of servers and everything else to another, or redirecting HTTP to HTTPS in one place, are layer 7 features you'll use.
How it picks a server
- Round robin: one each, in turn. Simple and fine when requests are similar in cost.
- Weighted round robin: bigger servers get a bigger share.
- Least connections: send to the server with the fewest active connections. Better when some requests are slow (reports, exports, file uploads) and others are instant.
- Hash-based (by IP or a key): the same client always lands on the same server. Useful for caches, but uneven when many users share one IP, like an office network.
Round robin is the usual default, and for most apps the choice of algorithm matters much less than the next two topics.
Health checks: the part that gives you availability
The load balancer regularly calls a URL on each server. If a server fails enough checks in a row, it's taken out of rotation until it recovers.
Laravel 11 and 12 ship with a health route out of the box, configured in bootstrap/app.php:
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
health: '/up',
)
// ...
/up answers 200 when the app boots without errors. That's a shallow check: is this process alive? You might be tempted to write a deep check that also tests the database, Redis and every external API. Be careful. If the shared database has a hiccup, a deep check fails on every server at once, and the load balancer removes all of them, turning a slow database into a full outage. Keep the load balancer's check shallow, and monitor dependencies separately.
Sessions: why users get logged out
Here's the classic. The file session driver, the default for years and still common in older apps, stores sessions on the local disk. (New Laravel 11 and 12 apps default to database, which avoids this, as long as every server talks to the same database.) A user logs in on server A, so their session lives on server A. The next request goes to server B, which has never heard of them. Logged out.
There are two fixes:
Sticky sessions. The load balancer sets a cookie and keeps sending that user to the same server. It works, and it's a quick patch. But load becomes uneven, a deploy or crash on that server still logs its users out, and you're back to depending on one machine.
A shared session store. Every server reads sessions from the same place, so it doesn't matter which one handles the request:
SESSION_DRIVER=redis # or "database"
CACHE_STORE=redis
This is the right answer almost every time. Servers become interchangeable, which is the whole point of having more than one.
The stateless rule: any server should be able to handle any request. If something lives only on one server's disk or memory (sessions, uploads, cache, locks), move it somewhere shared before you add the second server.
The rest of the checklist
- Uploads: store files on S3 (or another shared disk) instead of local
storage/, or half your images will 404. - Scheduled tasks: every server runs the scheduler, so every task runs once per server. Add
->onOneServer()to tasks that must run once. It needs a shared cache driver to coordinate the lock. - Real client IPs: behind a load balancer,
$request->ip()returns the load balancer's address. Configure trusted proxies so Laravel readsX-Forwarded-For, for example$middleware->trustProxies(at: ...)inbootstrap/app.php. Trust only your load balancer's addresses where you can. - HTTPS detection: the same trusted proxy setup tells Laravel the original request was HTTPS, so generated URLs don't flip to
http://. - Queue workers: they already pull from a shared queue, so they scale out happily. Just make sure jobs don't depend on local files.
If you remember one thing
Adding a load balancer is the quick part. Making your app ready for one is the real work: shared sessions, shared files, scheduled tasks that run once, and shallow health checks. Do those first and the second server really is just "more capacity".
Which one caught you out the first time you scaled past a single server: sessions, uploads or the scheduler running everything twice?

Be first to comment it...