- 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
9 Performance Quick Wins for PHP Sites That Take Minutes, Not Rewrites
About Post
Most slow PHP sites aren't slow because of PHP. They're slow because of a handful of boring settings nobody switched on, an image that weighs more than the rest of the page combined, and one query doing a full table scan on every request.
The good news: boring problems have boring fixes. None of the wins below needs a rewrite, a new framework or a bigger server. Most take minutes. Together they can change how a site feels.
First, measure for five minutes
Before touching anything, find out where the time goes. There are only two places:
- Server time: how long until the first byte arrives (TTFB). Open DevTools, Network tab, click the HTML request, look at "Waiting for server response".
- Browser time: everything after that. Images, scripts, fonts, layout. Lighthouse in Chrome DevTools gives you a decent summary.
A slow TTFB means look at PHP, the database and the server. A fast TTFB with a slow page means look at the front end. Fixing the wrong half is how people spend a week and gain nothing.
Server-side wins
1. Make sure OPcache is on, and tuned
Without OPcache, PHP reads and compiles every file on every request. With it, compiled code stays in memory. It's bundled with PHP, but I still find it disabled or starved of memory more often than you'd expect. Check php -i | grep opcache (or phpinfo() on the web server, then remove it) and aim for something like:
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
The gotcha is the last line. With validate_timestamps=0, PHP stops checking whether files changed, which is faster, but it also means your deploy must reload PHP-FPM (or Apache) or the old code keeps running. Put the reload in your deploy script.
2. Cache the framework's own work
Laravel spends time on every request loading config files, registering routes and discovering events. In production, cache all of it in one go:
composer install --no-dev --optimize-autoloader
php artisan optimize # config, routes, events and views
One trap: after config:cache, the .env file isn't read any more, so any env() call outside your config/ files returns null. Read env values in config files only, and use config() everywhere else.
3. Cache the expensive answers
The dashboard numbers that take a heavy query but only change a few times an hour don't need to be computed for every visitor:
$stats = Cache::remember('dashboard.stats', now()->addMinutes(10), function () {
return [
'open_requests' => MaintenanceRequest::where('status', 'open')->count(),
'overdue_invoices' => Invoice::overdue()->count(),
];
});
Use Redis or Memcached as the cache store in production rather than files when you can. And decide upfront how stale each value is allowed to be. That's a product question, not a technical one.
Database wins
4. Index what you filter and sort by
The single most common cause of a slow page I see is a query with a WHERE or ORDER BY on a column with no index. Run EXPLAIN on your slowest queries. If you see type: ALL on a big table, that's a full scan. A composite index matching the query (for example (status, created_at)) often turns seconds into milliseconds.
Turn on MySQL's slow query log in production so you find these from evidence instead of guesses.
5. Kill the N+1 queries
A list page that runs one query for the list and then one more per row is fine with 10 rows and painful with 500. Eager load with with(), and in development add Model::preventLazyLoading(! app()->isProduction()); in a service provider so Laravel throws an exception the moment it happens.
Don't do slow work inside the request
6. Queue it
Sending email, generating a PDF, resizing an upload, calling a third-party API: the user doesn't need to wait for any of these. Push them to a queue and respond immediately.
Mail::to($tenant)->queue(new ReceiptMail($payment));
GenerateContractPdf::dispatch($contract);
This is often the biggest perceived speed-up of the whole list, because the slowest part of a request is usually waiting on someone else's server.
Browser-side wins
7. Fix the images
Images are usually the heaviest thing on the page. Three fixes cover most of it:
- Serve modern formats (WebP or AVIF) at the size they're actually displayed. A 4000-pixel photo shown in a 400-pixel card is pure waste.
- Add
loading="lazy"to images below the fold. Not to the hero image: lazy-loading the main image makes the page feel slower. - Always set
widthandheightattributes so the browser reserves space and the layout doesn't jump.
8. Let the browser cache your assets properly
If your build tool (Vite, for example) puts a content hash in file names like app-3f9a1c.js, those files can be cached for a year, because a new version gets a new name. In Apache, an .htaccess in the build folder can do it:
<IfModule mod_headers.c>
Header set Cache-Control "public, max-age=31536000, immutable"
</IfModule>
Only do this for fingerprinted files. Your HTML and anything without a hash in its name should not be cached like this, or users will be stuck on old versions.
9. Compress text responses
HTML, CSS, JS and JSON compress extremely well. Make sure gzip or Brotli is enabled on the web server. It's a config line, and it shrinks every text response.
The order I'd do them in: measure, then OPcache and php artisan optimize, then the slow query log and indexes, then queues, then images and caching headers. The first three are server settings you can do in an afternoon.
The quick-wins checklist
- OPcache on, with enough memory, and PHP reloaded on deploy.
composer install --no-dev -oandphp artisan optimizein the deploy script.- Expensive, rarely-changing values cached with a clear expiry.
- Slow query log on, indexes for real query patterns, no N+1.
- Email, PDFs and third-party calls on a queue.
- Images resized, modern formats, lazy below the fold, dimensions set.
- Long cache headers for hashed assets, compression for text.
Which of these did you find switched off on a server you inherited? For me, it's OPcache surprisingly often.

Be first to comment it...