- 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
WebSockets vs Server-Sent Events vs Polling: Choosing Real-Time Without Regret
About Post
Someone in the planning meeting says "it should update live". Ten minutes later, the ticket says "add WebSockets", and nobody has asked the more useful question: how live, and in which direction?
A maintenance request changing from "open" to "in progress" doesn't need the same machinery as a multiplayer game. Real-time on the web comes in four flavours, and the cheapest one that does the job is usually the right one. Let's compare them honestly.
The restaurant version
You're waiting for your food. There are four ways to find out when it's ready:
- Polling: you walk to the counter every two minutes and ask. Simple, but mostly the answer is "not yet".
- Long polling: you ask once, and the waiter stands next to you until it's ready, then tells you. You ask again for the next thing.
- Server-Sent Events (SSE): there's a screen on the wall that shows order numbers as they're ready. Information flows one way, to you, as it happens.
- WebSockets: you and the kitchen have a phone line that stays open. Either side can talk at any time.
Keep that picture in mind. Now the details.
Polling: boring, and often enough
The client asks the server for the latest state on a timer. That's it: normal HTTP requests, normal caching, normal authentication, works through every proxy and firewall on earth.
The cost is wasted requests and delay. Polling every 10 seconds means updates can be up to 10 seconds late, and every open tab is making requests even when nothing has changed. For a dashboard that a handful of staff keep open, or a "your report is being generated" screen, that's completely fine.
Long polling improves the delay: the server holds the request open until there's news (or a timeout), then the client immediately asks again. It was the standard trick before WebSockets were widely supported. Today it mostly survives as a fallback.
Server-Sent Events: the underrated one
SSE is a long-lived HTTP response that the server keeps writing to. The format is plain text:
event: status
id: 17
data: {"status":"in_progress"}
And the browser has a built-in client, EventSource, that parses it and reconnects automatically, sending the last event ID it saw so the server can resume:
const source = new EventSource('/requests/42/stream');
source.addEventListener('status', (event) => {
const { status } = JSON.parse(event.data);
showStatus(status);
});
It's one-way: server to client. But that covers a lot of "live" features: notifications, progress bars, status changes, activity feeds. If you've watched an AI chat answer appear word by word, you've seen SSE-style streaming; the major LLM APIs stream their responses this way.
Watch out for two things. Over HTTP/1.1, browsers limit how many connections a page can open to one domain, and each SSE stream uses one, so many tabs can starve each other (HTTP/2 largely removes this). And proxies that buffer responses will hold your events back; with Nginx, the X-Accel-Buffering: no header or turning off proxy buffering fixes it.
WebSockets: a real two-way channel
A WebSocket starts as an HTTP request that asks to "upgrade", then becomes a persistent, two-way connection. Both sides can send messages at any moment with very little overhead per message.
That's what you want for chat, collaborative editing, live cursors, games, or anything where the client sends frequent small messages too. It's also the most demanding option to run: a server that holds many open connections, load balancers configured for long-lived connections, and a way to fan messages out across multiple servers.
In Laravel, you rarely write raw WebSocket code. You fire a broadcast event on the server and listen with Laravel Echo on the client:
window.Echo.private(`requests.${requestId}`)
.listen('RequestStatusUpdated', (e) => showStatus(e.status));
The WebSocket server itself can be a hosted service like Pusher or Ably, or Laravel Reverb, Laravel's own first-party WebSocket server, which you run yourself and which speaks the Pusher protocol, so Echo works with it unchanged. php artisan install:broadcasting sets the pieces up. See the Reverb docs for running and scaling it.
Side by side
| Polling | SSE | WebSockets | |
|---|---|---|---|
| Direction | Client asks | Server to client | Both ways |
| Latency | Up to the interval | Near instant | Near instant |
| Transport | Plain HTTP | One long HTTP response | Upgraded connection |
| Reconnect | Not needed | Built in | You (or your library) handle it |
| Infrastructure | Nothing new | Long-lived responses | A WebSocket server |
| Best for | Slow-changing data, few users | Feeds, progress, notifications, AI streaming | Chat, collaboration, games |
The PHP gotcha
Here's the thing that surprises PHP developers. In a classic PHP-FPM setup, each request occupies a worker process until it finishes. A long-lived SSE stream or long poll holds that worker the whole time. A few hundred open tabs can exhaust your worker pool, and then normal page loads start queueing.
That's exactly why Reverb runs as its own long-running process rather than inside your FPM workers. If you want SSE at scale from a PHP app, think about where those connections will live before you ship it.
Whatever you pick: real-time is a hint, not the truth
Connections drop. Phones go into tunnels, laptops sleep, mobile apps get suspended in the background. Messages sent while the client was away are simply missed.
Design rule: treat real-time messages as "something changed, here's the gist", and keep your normal API as the source of truth. On reconnect, refetch the current state. Then a missed message costs a refresh, not a wrong screen.
For mobile apps, remember that a backgrounded app usually can't hold a socket open at all. If the user must know about something while the app is closed, that's a push notification's job, not a WebSocket's.
How I'd choose
- Does the client need to send frequent messages back? Yes: WebSockets.
- Does the server need to push updates as they happen? Yes: SSE (or broadcasting, if you already run a WebSocket server).
- Is a delay of several seconds fine, with modest traffic? Polling, and move on to the next ticket.
Which one do you reach for by default, and has it ever turned out to be overkill (or not enough)?

Be first to comment it...