- 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 Testing Basics: How to Find Your App's Breaking Point Before Your Users Do
About Post
Every application has a breaking point. A number of users, or requests per second, where pages slow to a crawl, errors start appearing and the database quietly gives up.
You don't get to choose whether your app has one. You only get to choose when you find out. On a quiet afternoon, with a test you control and a coffee in your hand? Or on the morning of a big launch, the first day of the month when everyone pays rent, or the day a post about your product goes viral?
Load testing is how you pick the quiet afternoon. It sounds like specialist work, but the basics are very approachable. Here's the process I'd follow, step by step.
Step 1: ask a specific question
"Is the app fast?" isn't a question a load test can answer. These are:
- Can the checkout flow handle our busiest expected hour with p95 response times under 500 ms?
- At what number of concurrent users does the error rate go above 1%?
- Does the API stay stable for four hours of normal traffic, or does memory slowly climb?
- What happens when traffic jumps suddenly, like after a push notification goes out to every user?
Each of those is a different kind of test, and knowing which one you're running changes everything else.
| Test type | What it does | Answers |
|---|---|---|
| Load test | Expected traffic, held steady | Do we meet our targets on a normal busy day? |
| Stress test | Keep increasing until things fail | Where is the breaking point, and how do we fail? |
| Spike test | A sudden jump in traffic | Do we survive a burst, and recover after it? |
| Soak test | Normal traffic for hours | Leaks, growing queues, connections not being released |
Step 2: pick where to test (not production)
Test against a staging environment that's as close to production as you can afford: same instance sizes, same database engine and configuration, a realistic amount of data. A query that's instant on a table with 500 rows can be painfully slow on the real one, so an empty staging database gives you a happy, useless result.
Two warnings. Don't load test production unless everyone involved has agreed to it and you know how to stop. And make sure your test doesn't hammer third parties: point payment gateways, SMS and email at sandboxes or fakes. Load testing someone else's API without permission is not a nice surprise for them.
Step 3: model what real users do
The most common load testing mistake is hitting one endpoint as fast as possible. Real users don't do that. They log in, browse a list, open a detail page, pause to read, maybe submit a form. Some actions are common, some are rare but expensive (a report export, a search with many filters).
A realistic scenario includes:
- A mix of journeys, weighted roughly like your real traffic. Your access logs or analytics are the best source.
- Think time between actions, so 100 virtual users behave like 100 people, not 100 scripts.
- Varied data: different users, different IDs, different search terms. If every request asks for the same record, you're mostly testing your cache.
Step 4: write the test
There are good tools for this: k6 (scripts in JavaScript, runs from the command line), Apache JMeter (long-established, with a GUI), Gatling and Locust (scenarios in Python). I like k6 because the test is just code you can keep in the repository. A simple version:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 }, // ramp up
{ duration: '5m', target: 50 }, // hold at expected load
{ duration: '3m', target: 200 }, // push past it
{ duration: '2m', target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const res = http.get('https://staging.example.com/api/invoices?page=1');
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(Math.random() * 3 + 1); // think time: 1 to 4 seconds
}
Run it with k6 run load-test.js. The thresholds turn your question into a pass or fail, which means you can run the same test in CI later and get a clear answer. A real script would also log in and walk through a few journeys; this one is simplified to show the shape.
Step 5: read the right numbers
A load test produces a lot of output. These are the numbers that matter:
- Percentiles, not averages. An average of 200 ms can hide the fact that one request in twenty takes four seconds. Look at p95 and p99: what the slowest 5% and 1% of users actually experience.
- Error rate. Timeouts, 500s and 502s. Fast errors are still errors, and some systems get "faster" when they start failing.
- Throughput. Requests per second actually served. When you add users but throughput stops rising, you've found a ceiling.
- Server-side metrics at the same time: CPU, memory, database connections, slow query log, queue length. The load tool tells you that it got slow. These tell you why.
The breaking point is a curve, not a crash. Plot response time against users. It stays flat, then bends, then shoots up. The bend is where your real capacity is, and it usually arrives well before anything actually falls over.
Step 6: find the bottleneck
In web apps, the same suspects show up again and again:
- The database. Missing indexes, N+1 queries that were invisible with one user, and locks when many requests update the same rows. Usually the first thing to break.
- Connection limits. Database max connections, or the number of PHP-FPM workers (
pm.max_children). When all workers are busy, new requests queue, and response times climb even though CPU looks fine. - Slow external calls made during the request. Each one holds a worker hostage while it waits.
- Missing caching on expensive, rarely changing data like settings, lookups or dashboard counts.
- The load generator itself. If the machine running k6 maxes out its own CPU or network, you're measuring your laptop, not your app.
Step 7: fix one thing, test again
Change one thing at a time and re-run the same test, so you know which fix helped. Keep the results of each run; a short table of "before and after" is the most convincing performance argument you'll ever bring to a planning meeting.
And keep the script. The best time to run a load test is before every big release, not once a year after something went wrong.
The checklist
- Start with a specific question and pick the matching test type.
- Test a production-like environment with realistic data, never third-party live APIs.
- Model real journeys with think time and varied data.
- Use thresholds so the test passes or fails clearly.
- Watch p95/p99, error rate and throughput, alongside server metrics.
- Fix one bottleneck at a time and re-run.
What broke first the last time you load tested something: the database, the workers, or something you never expected?

Be first to comment it...