- 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
Processes vs Threads vs Async: How Servers Handle Many Users at Once
About Post
A thousand people hit your site at the same moment. Your server has a handful of CPU cores. Somehow, most of them get a response in well under a second.
How? The answer depends on your stack, and it's different for PHP, Node.js, Java or Go. Understanding it explains a lot of things that otherwise feel random: why one slow API call can take down a PHP site, why one heavy loop can freeze a Node app for everyone, and why "just add more workers" sometimes makes things worse.
The restaurant kitchen
Picture a kitchen taking orders. There are three classic ways to run it.
Processes: many separate kitchens. Each order gets its own small kitchen with its own cook, fridge and tools. Nothing is shared, so one cook's mess never spills into another's. But kitchens are expensive, and you can only fit so many in the building.
Threads: many cooks in one kitchen. Several cooks share one kitchen, one fridge and one set of knives. Cheaper than separate kitchens, and they can hand things to each other. But two cooks can reach for the same pan at the same moment, so they need rules about who touches what.
Async: one very organised cook. One cook puts a pot on to boil, starts the oven, takes the next order, and checks back when a timer rings. She never stands watching water boil. She's brilliant at juggling lots of waiting. But if one order needs ten minutes of non-stop chopping, every other order waits.
Those are processes, threads and an event loop. Now let's see who uses which.
PHP-FPM: a pool of processes
A classic PHP app behind Nginx or Apache runs on PHP-FPM, which keeps a pool of worker processes. Each worker handles one request at a time, from start to finish, then takes the next one. Every request starts with a clean slate: Laravel boots, handles the request, and everything is thrown away.
That model is wonderfully simple. A memory leak or a crash affects one request, not the whole server. There's no shared state between requests to corrupt.
The catch is the pool size. It's set in the FPM config (example values):
pm = dynamic
pm.max_children = 20 ; hard limit on parallel requests
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500 ; recycle workers to contain leaks
If all workers are busy, new requests queue. Now imagine your app calls a slow payment gateway or a third-party API that takes several seconds to reply. Every worker waiting on that call is doing nothing, but it's still occupied. A few seconds of slowness from a partner can use up the whole pool, and suddenly unrelated pages time out.
The fixes: set timeouts on every outgoing HTTP call, move slow work to queued jobs, and size pm.max_children from memory, not hope. A rough guide is the RAM you can give PHP divided by the memory one worker uses. Setting it higher than that just swaps "slow" for "server out of memory".
Node.js: one event loop
Node runs your JavaScript on a single thread with an event loop. When code makes a database query or an HTTP call, Node doesn't wait. It registers a callback (or a promise), moves on to the next request, and comes back when the result is ready. One process can juggle a very large number of connections, as long as they're mostly waiting on I/O.
Under the hood there's a small thread pool too (libuv's, four threads by default) for things the operating system can't do asynchronously, like some file system work, DNS lookups and certain crypto functions. But your JavaScript runs on one thread.
Which is exactly the catch. CPU work blocks everyone:
app.get('/report', (req, res) => {
// ❌ synchronous file read + heavy loop: every other user waits
const rows = JSON.parse(fs.readFileSync('payments.json', 'utf8'));
res.json(buildYearlySummary(rows));
});
app.get('/report', async (req, res) => {
// ✅ non-blocking I/O; heavy CPU work moved to a worker or job
const rows = JSON.parse(await fs.promises.readFile('payments.json', 'utf8'));
res.json(await runInWorker('yearly-summary', rows));
});
(runInWorker stands in for your own helper around worker_threads or a job queue.) The rule in Node: never block the loop. Use async APIs, and push CPU-heavy work like image processing, PDF generation or big calculations to worker threads or a background queue. To use all your CPU cores, run several Node processes, with a process manager like PM2, cluster mode, or multiple containers.
Threads: the Java, .NET and Go way
Many other platforms handle each request on its own thread inside one long-running process. Threads are lighter than processes and share memory, so caches, connection pools and configuration are loaded once and used by everyone.
The price is that shared memory brings back the race conditions and locks we'd rather not think about. And traditional OS threads aren't free either, so very high concurrency used to need careful tuning. Modern runtimes soften this: Go's goroutines and Java's virtual threads are very lightweight, letting you write simple blocking-style code that the runtime schedules efficiently.
Side by side
| Processes (PHP-FPM) | Event loop (Node.js) | Threads (Java, Go, .NET) | |
|---|---|---|---|
| Requests per worker | One at a time | Many, interleaved | One per thread, many threads |
| Shared memory | None between requests | Everything, one thread | Everything, many threads |
| Great at | Isolation, simplicity | Lots of I/O waiting | Mixed I/O and CPU work |
| What hurts | Slow external calls tie up workers | CPU work blocks everyone | Races, locks, tuning |
| Scale up by | More workers, more servers | More processes, more servers | More threads, more servers |
PHP is getting a bit of everything
PHP isn't stuck with one model. Laravel Octane runs your app on long-lived servers like FrankenPHP, Swoole or RoadRunner, so the framework boots once and stays in memory. That removes the boot cost from every request, but it also brings back a threads-style risk: state you leave in a static property or a singleton can leak into the next user's request. PHP 8.1's Fibers and libraries like ReactPHP and Amp make event-loop style code possible too.
For most Laravel apps, though, plain PHP-FPM with sensible timeouts and queued jobs scales a long way. The model's simplicity is a feature.
The one thing to remember: every model has a resource it runs out of. PHP-FPM runs out of workers, Node runs out of event-loop time, threaded servers run out of threads or memory. Know which one your stack has, and protect it: timeouts for waiting, queues for heavy work.
A quick diagnosis guide
- PHP site slows down when a partner API is slow: workers are stuck waiting. Add timeouts, move the call to a job.
- Node app freezes for everyone during one heavy request: the event loop is blocked. Find the sync or CPU-heavy code.
- Threaded app has rare, unreproducible data bugs: look for shared mutable state.
- Octane app shows one user's data to another: state is surviving between requests.
Which model does your main stack use, and which of these failure modes have you actually met in production?

Be first to comment it...