Backend performance best practices
🐇
Fast backends stay fast under load.
Performance design makes websites run fast - from development to production, from backend to frontend. Do it for your wallet, your users and the environment.
We want you to encourage to design for performance and scalability. And that is all about thinking a bit ahead. Speed matters for your users and for SEO. You - the responsible PHP developer - may have more responsibility than you think.
# Time to first byte
The TTFB depends on how fast the service can compute. Your code plays a major role. Also see the PHP processes article to learn about limits when executing PHP. See our understand performance article on how to analyze backed performance problems.
# Prepare to cache
If you begin developing, you might not instantly utilize a pair of multi gigabyte Redis servers. Still: make sure to implement caching early on and to use abstraction, so you can later on switch to those caching machines when you need them. Available caching solutions on fortrabbit:
- File: Disk storage is not very fast.
- Database: Faster than disk. Use if you need to cache data for a long time.
- APC: Aside from opcode caching which happens automatically, you can use APC as an object cache very similar to Memcache or Redis.
- Valkey: Modern key value im memory caching service
# Reduce I/O
It's always a good idea to reduce file input/output operations on the disk to the minimum. In PHP this means:
- PHP includes: Reduce amount of includes as much as possible. Always use absolute path names, which reduces the amount of lookups.
- Avert files: Don't use file-sessions, file-caches or anything
file-*, if you can replace it with an in-memory cache or even the database. - Outsource static files: Put your static files on an object storage. Sure, they could be delivered very fast from local, but still, they will create I/O which your (PHP) App will be missing.
- Shrink your loader chain: Make sure you load only the classes (files) you need. For a production App (in which code changes do not occur often) you can set
apc.statorpcache.validate_timestampsto0, which reduces I/O on.phpfiles even further, but requires an APC/OPcache flush for changed files to apply.
# Decouple, but loosely
Leverage the power of the cloud: Span your App across multiple services. If you need image or video encoding: use an external service for this. If you want to send mass mails: use an external service for this. Why? Because it balances the load of your App and thereby gives it more resources for each individual task it has to perform.
However, if one of those external service (temporarily) breaks, make sure you can switch it off in seconds! You still want your shopping basket to run, if your image transformation has a problem.
# Prepare for CDN
If you're planning on growing large and expect a lot of traffic, you will end up putting your static files (images, videos, css and js files, ...) behind a Content Delivery Network. Nowadays, you can do this pretty effortless with specialized services. Some services work best with a dedicated (sub)domain for your static contents, such as img.yourdomain.com. If you expect to use them in the future, you should implement the required structure from the start. Also a good precaution is to setup your cache headers properly from the start.
# Database considerations
Very common: check your JOIN queries! If they ran fast when your dataset was small, it doesn't mean they still do with a bigger dataset. Utilize caches to buffer costly databases results. Database optimization could easily fill a whole book — or books. Read our dedicated MySQL performance tips.
# Static file separation
Sure, a request to a static file can be delivered faster than a request handled by a dynamic script - nonetheless, the more static requests are performed by your App, the more it has to do overall. More is more in the end. If you split up the traffic in dynamic and static requests, by utilizing a cloud hosting service, all the requests for static files are not handled by your App anymore but by another server somewhere else. Resulting, your App on fortrabbit acts as the motor for your PHP scripts, while a host dedicated to delivering static files takes care of the rest.
# Profile your code
Web applications are usually fast after the launch, but degrade over time. They receive more requests and process more data. You add more features and at some point everything or some parts of your app become slow. Profilers give you deep insights of your code and all dependencies that are involved to handle requests. XDEBUG profiler and XHPROF are the defacto open source standard, but you need additional tools to visualize the data. The blackfire profiler makes it really easy to start profiling in minutes.
# Use load testing
We advise to put your website under some controlled stress to see when it will break. There are tools you can use from your computer to fire up a couple of simultaneous requests. This way you can see how the website will behave before your first unlucky visitors will find the bottleneck for you.
# Reduce max execution time
This is an opinionated topic. If you come from searching 504 time out errors, you will often read to increase the max_execution_time setting to allow a certain process to finish it's task.
By the way: You can adjust this setting with your environment under "PHP settings" in the dashboard.
In some cases that makes sense, but it's often a poor design decision. Image transformations with imageMagick are often long running, therefore you might want to increase the execution time to avoid time outs. But, as stated here often: long running tasks should best be separated from the frontend tasks into the background. With the jobs component you can outsource jobs.
Frontend requests should always return a swift answer. The number of PHP processes is limited. When all PHP processes are occupied with long running tasks, new requests need to wait. That can easily pile up. A lower max execution time limit often results in faster errors. And that's often what you want. When making an API call to an external service, usually that reply should be there within a second, how long should you wait for it max? Maybe 10 seconds is reasonable. It's not likely that there will be an answer when you wait longer.
So for most cases, short is better.
# Block and limit bots
A lot of web traffic is generated by crawling bots. There are bad ones and good ones. Did you know: A wrongly configured navigation plugin can cause a bot to get stuck in a loop visiting an endless number of pages within your website. This can cause high load, traffic and ultimately spam your template caching folder.
Enable our WAF feature.
Set a crawl delay to limit unnecessary crawling of your website if it is not updated very frequently. The craw-delay directives in robots.txt are supported by good bots such as search engines, commercial bots, SEO bots.
# Swap issues
In some cases swap usage by the application is not possible. In these cases you might see dreaded white-pages and along going error messages in the log: "Allowed memory size of 1234.. bytes exhausted (tried to allocate 234 bytes)." This should be understand as an urgent reminder to scale up the PHP plan.
Found a tpyo?Edit