I’m scaling our startup using Laravel/PHP to half a million users – and its going terrible

TLDR: Scaling our Laravel environment based on HAProxy and multiple NGINX/PHP-FPM nodes. All nodes constantly get out of control consuming heavy loads. Long running scripts have been eliminated so far yet our web servers do not serve Laravel well.

- 2000 reqs / sec (200k daily users)
- Our application performance is fine, got a very few long running requests for e.g. stream downloadable files.
- App is running behind an HAProxy und multiple self provisioned NGINX/FPM containers (sharing NFC mounted storage)
- our queue is processing more than 5-10 mio jobs per day (notifications / async stuff) taking 48 cores for just handling those
- Queries were optimized based on slow logs (indices were added for most tables)
- Redis is ready for use (but no caching strategie was found yet: What to cache where and when?)
- 2000 reqs/sec handled by 8x 40 cores (more then enough) + 8x 20 RAM

How did you guys manage to scale applications on that size (on-premise based)?

There are tons of FPM parameter and NGINX guides out there - which one to follow? So many different parameter, too much that can go wrong.
________
I feel just lost. Our customers and company are slowly going crazy.

________
**UPDATE 1: Guys, I got a bunch of DMs already and so many ideas! We're currently investigating using some APM tools after we got some recommendations. Thank u for each reply and the effort of each of you** ❤️
________
**UPDATE 2: After some nightshift, coffee and a few Heineken we realized that our FPM/NGINX nodes were definitely underperforming. We setup new instances using default configurations (only tweaked max children / nginx workers) and the performance was better but still not capable of handling the requests. Also some long running requests like downloads now fail. So we realized that our request / database select ratio seemed off (150-200k selects vs 1-2k requests). We setup some APM (Datadog / Instana) and found issues with eager loading (too much eager loading instead of missing though) and also found some under-performing endpoints and fixed them. Update follows...**
________
**UPDATE 3: Second corona wave hit us again raising the application loading times as well as killing our queues (> 200k jobs / hour, latency of 3 secs / request) at peak times. To get the thing back under control we started caching the most frequent queries. Resulting our Redis in running > 90% CPU - so the next bottle neck is ahead. While our requests and queue performs better there still must be some corrupt jobs causing delays. Up next is Redis and our database (since its also underperforming under high pressure). In addition to that we were missing hardware to scale up that our provider needs to order and implement soon. 🥴 Update follows...**
________
**UPDATE 4: We also radically decreased max execution times to 6 seconds (from 30) and database statements to 6 seconds as well. Making sure the DB never blocks. Currently testing a Redis cluster. Also contacted MariaDB enterprise team for profiling DB settings. Streamed downloads and long running uploads need improvements next.**
_______
**Update 5: Scaling Redis in an on-premise environment feels more complicated then we thought. Struggling with configuring the cluster atm. Didn't found a proper solution and moved from Redis to Memcached for caching. Going to see how this performs.**

________
Props to all sys admins out there!

52 thoughts on “I’m scaling our startup using Laravel/PHP to half a million users – and its going terrible”

  1. Never scaled that high before, hope it goes better for you…

    At a certain point though, have you started separating dedicated services? Have certain aspects of your environment running on different machines – starting down the road of microservices? Just curious.. not sure what your needs are.

    Reply
  2. What sort of caching are you using? If you haven’t done so already, move your static assets to s3 sand create a cdn cloudfront distribution. For assets that have to be served from your app, ensure you are using https caching headers (cache-control: max-age …).

    Profile the most common user actions. What can you cache further? Can you use redis to cache anything that hasn’t changed. Invalidate the cache keys items via model listeners and other relevant events.

    Test your nginx configuration is a staging environment. Use something like jmeter to stimulate X concurrent users hitting your server.

    Try to understand – is your app choking because it’s running out of memory, starving for a database connection resource etc.

    If you’ve not done already, move any long running tasks that don’t need to be done right away into a (non-sync) queue (signs like you’ve already done this). Not clear to me why you need so many cores to process that number of requests… Anything you can do to lighten that cpu load?

    God speed! Let us know how you got on.

    Reply
  3. Your long running requests – have you considered moving those to other infrastructure away from the monolith? Long running requests are heavy on resource, especially so if they’re doing any heavy lifting.

    Edit: Assuming they’re a good % of your request total.

    Reply
  4. We run similar numbers without a problem. We run in AWS though. That said, I think Caching seems to be your primary missing link here. For server side, look at Redis.

    Also consider something like CloudFlare. With PageRules You can set fine grain controls over which URLS/Assets are cached and for how long. You can also get fancy and use CloudFlare workers. This way you can serve things up in an Edge environment which exists in the space between your server side code and the browser. It can be very effective if deployed correctly.

    Both concepts here about trying to leave your web servers for the transactional aspects only, and defer everything else.

    Reply
  5. We aren’t anywhere close to that many users in a work app but consider this pattern expanding on u/fuze-17’s note about separating your services.

    1. Separate your queues physically into a notification queue and an async (assuming these are jobs) queue. We did this so we could have more control over the resources/queue and the amount of workers. Also helped us find inefficiencies in some of our jobs.
    2. Can you utilize caching, maybe offload that to a faster system like Redis v. local?
    3. Have a completely separate code base/service handling downloads / streaming of assets.
    1. Another thought, can you utilize a CDN to help deliver that content?
    4. Assuming there was some architecture decision that happened somewhere. Are you running all your services “on-prem” and could moving some of those to the cloud be beneficial?
    5. Are the bottlenecks at the CPU/application or are they network related?

    These are pretty broad examples not knowing the specifics but hopefully helpful.

    Reply
  6. Never been at the level, so the guides I usually follow are probably of no help. But if application performance is fine, you might just need to increase the limits on the number of proccesses for Nginx and FPM. But like I said, I’ve never been at that level.

    Have you considered going with a serverless solution? AWS Lambda doesn’t have native PHP support, but there are ways around that.

    Reply
  7. I think that you could run this for < $300/mo on Vapor With 512 MB instances those requests would cost like $40/mo and if you can fit into a 64 kB SQS payload with your jobs, your queues would cost like $100/mo.

    Reply
  8. What exactly is crashing servers or causing a bottleneck?

    At the end of the day you can either add more CPU, memory, faster disks OR optimize code for existing hardware

    It sounds like you may need to investigate exactly what is happening on your servers with a tool like Datadog or Prometheus

    Reply
  9. > 2000 reqs/sec handled by 8x 40 cores (more then enough) + 8x 20 RAM

    Am I misreading that? A single core should be able to take 50 req/s at least. So 40 cores not 8 x 40. But normally you should be able to get a lot more out of it. As long as all your PHP requests are not doing image processing and PDF generation, this sounds awfully slow.

    How many queries are your requests doing? Your database is on a separate server, right?

    I’ll add some concrete advice in separate posts.

    Reply
  10. Redis. It’s a cool tool. First of all, open up your config or .env and make sessions and cache use redis right now.

    Then, caching itself.

    Do you have any semi-static responses? I’m not sure about the nature of your site, but you should see yourself what’s getting most hits. Maybe everyone’s looking at the same index page or requesting the list of featured news? Maybe there’s some inner service producing list of menu items? If you cache a thing like that for 60 seconds, you are saving processing power and over 10k DB queries at least.

    You can also use nginx to cache full responses (especially if they’re not session-dependent), but at the start it’s easier to cache only on Laravel. That being said, you might be able to serve over a thousand requests per second with successful nginx caching, I’ve reached as high as 6k req/s for sites with very few (around a dozen) pages.

    Reply
  11. I was handling a LOT of queued jobs, but not that many (I’d estimate 1m/day). Since I’d be running the queue from the db, then fetching records from the db, then updating records from the db, it was an extremely DB heavy process. I found the database was WAY too slow to use as a queue driver.

    Since you mention Redis not being used for caching, I’ll guess it’s not your worker driver. I’d say above caching, move to Laravel Horizon on Redis for a nice speed boost. If you put it on a different “database”, you should be able to clear your caches without clearing the jobs.

    Edit: Run as a micro HA with 4 DO droplets. Web, Worker, Redis, DB.

    Reply
  12. >2000 reqs / sec (200k daily users)

    In the other comment, you mentioned 100 listeners? did you cache the events? laravel will always load the events on every request, this can cause huge performance issues

    also separate routes based on usage and remove unnecessary middleware. dont load code that isnt used.

    >Our application performance is fine, got a very few long running requests for e.g. stream downloadable files.

    Dont stream downloadable files with php, let nginx do the work or move to s3 or alternatives

    >App is running behind an HAProxy und multiple self provisioned NGINX/FPM containers (sharing NFC mounted storage)

    i/o problems? check your disk usage

    >our queue is processing more than 5-10 mio jobs per day (notifications / async stuff) taking 48 cores for just handling those

    bulk notifications. dont run jobs that do the same thing over and over again. if you can bulk it the better. or create a long terms job that is going to execute a given bulk.

    >Redis is ready for use (but no caching strategie was found yet: What to cache where and when?)

    everything that gets accessed more than 5-10% of your usebase. into redis you go. make jobs that update the contents on crud. You can also levreage nginx to responce cache, the more static data nginx delivers the better

    >Queries were optimized based on slow logs (indices were added for most tables)

    the less you load from the database the better, setup profiling and monitoring for access times

    >2000 reqs/sec handled by 8x 40 cores (more then enough) + 8x 20 RAM

    thats overkill tbh. you dont need half of that

    Start with setting up timers and log the data from your nodes. see where you get the most time wasted and work from there. there is no such thing as over caching. but be careful with data updates.

    Reply
  13. Of course, you should look for your actual bottlenecks. Maybe you’re doing 6200, 1800 or 60 queries per request instead of 7. I have done that. But here goes some microoptimization tips.

    “`
    # nginx.conf
    worker_processes 1;
    “`

    Unless you’re serving insane amounts of static files, nginx is mostly drinking coffee while waiting for php to respond. So a single worker is enough on PHP sites. `auto` (= number of cores) is a waste.

    “`
    # nginx.conf
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    “`

    See if you want explanations https://thoughts.t37.net/nginx-optimization-understanding-sendfile-tcp-nodelay-and-tcp-nopush-c55cdd276765

    Regarding PHP-FPM it’s even simpler. Just these two:

    “`
    # pool.d
    pm = static
    pm.max_children = 80
    “`

    Adjust `max_children` so you are utilising nearly all cpu power. That’s it.

    In fact you can share your nginx and fpm conf. Sometimes people add some unfourtunate directives that are detrimental to performance.

    Reply
  14. Events can query database.

    On demand requests are never ever allowed to query the database.

    An event.
    – typically a write or update to the dB

    On demand
    – a request

    If your archecture doesn’t follow those rules you will lose!

    Reply
  15. “Our application performance is fine, got a very few long running requests for e.g. stream downloadable files.”

    How are you defining fine? What’s the average page load time and query count for the highest traffic endpoint?

    Reply
  16. Mounts on NFC are and will keep staying a bottleneck, especially for PHP files, where OPCache has to revalidate files every few seconds.

    Just this change should make things better.

    Reply
  17. I would like to suggest the following:

    \- [https://github.com/barryvdh/laravel-debugbar](https://github.com/barryvdh/laravel-debugbar)

    \- The information this displays is holy cow amazing: SQL statement(s) used, Views, memory usage, request duration and memory, etc.

    \- Use Cache for static information

    \- A great video (free): [https://www.youtube.com/watch?v=HadES55O4Wk](https://www.youtube.com/watch?v=HadES55O4Wk)

    \- A FANTASTIC course that helped me find multiple issues (COST), worth every penny (or whatever your currency is) [https://gumroad.com/d/6ec4d17b04690de71ff923c9f6b81462](https://gumroad.com/d/6ec4d17b04690de71ff923c9f6b81462)

    \- Pay for a Consultant like Spatie, Jonathan Reinink, Povilas Korop, etc to assist in finding and fixing (some/al) of your issues.

    \- I suspect they can help you with your current issues as well as identifying long term issues.

    Reply
  18. You need to stop requests reaching the backend unnecesarily, I highly recommend Fastly for this issue. It uses Varnish cache, you just need to cache endpoints that are requested a lot and have data that doesn’t change that frequently.

    I’m not related to Fastly in any way, but I’ve seen a Symfony project that had around 1k requests per second and it leverages pretty well. Good luck!

    Reply
  19. Yeah, so first things first, the database connection tends to be a bottleneck.

    1. Move sessions to a redis caching server. This is an easy win.
    2. Get the queue off the database and onto a dedicated queuing system. AWS SQS is incredibly easy to set up, or use something like RabbitMQ. You can also use redis for this.
    3. Get static assets like images off your servers and onto a CDN.

    Reply
  20. Why aren’t you already using redis for queues and session? Get that shit out of your file system/database. Redis cache the common queries if your db is what’s struggling. Hire a DBA to property optimize and index your tables based on the queries you run. Laravel isn’t very efficient with a lot of its relationships so you may have to phase those out for less intense queries. Look at the query log for common requests on your application and audit multiple of the same queries and stuff like that.

    I’m currently handling about 5x your traffic on 3x 8gb web servers (nginx, php fpm), two 16gb mysql servers (one primary one secondary/failover).

    Don’t serve static assets from your main web servers either if you can help it. Put it on s3 behind cloudfront or cloudflare. Or move them to a separate server using nginx and some cache like varnish.

    Should also be mentioned but hopefully it’s already the case – you should be using php artisan config:cache and optimize. This speeds up initial load significantly.

    Reply
  21. Is your haproxy set to round robin or leastconn?

    >It depends on what’s the protocol and the use case to balance. For anything where the amount of connections is correlated with the load/usage, it’s better to use leastconn. Because of the way networks and applications work, it’s pretty much always true and you’re better off using leastconn by default

    I’d second setting up new relic and/or blackfire.io to really dig into your application and find where bottlenecks exist.

    Redis – There isn’t really a ‘strategy’ here – there are 2 or 3 layers of caching to consider. UI/View layer, which focuses on assets, usually handled by nginx/apache. DB – which is handled by memcached or redis. What this does is cache queries automatically. Repeat queries pull from redis while unique queries go to the db. Lastly, application caching where you would read/write directly to cache for whatever reason. I don’t recommend this. You can also consider something like varnish but it’s more complicated than I feel it’s worth. Trying to inject custom regions can get tricky and not something to try under pressure.

    DB setup – if you haven’t done this, I’d recommend a db replication set with 2 databases, one for reads, one for writes. All db writes go to db-a, but all reads happen on db-b. Laravel handles it nicely. I can’t say I’ve seen huge performance increases with this, but definitely an increase and definitely worth it.

    You say sharing via NFC filesystem, I’m not sure what you’re referring to here, if your entire application is on a shared filesystem such as NFS, I’d say oops. Only assets should be on shared storage, and only then once you have caching at the server and preferably CDN level.

    Reply
  22. Welcome to a completely different world 🙂 There is no single magical way to scale an app. I would like to share some of the common practices I can think of right now. The list is not even close to being complete.

    Caching strategy is unique for each application so I will not get into that subject. There are many comments already mentioning the principles of caching.

    # Database

    1. [Use separate read and write servers.](https://laravel.com/docs/8.x/database#read-and-write-connections) Increase the number of read servers as required.
    2. Use a connection pool for database connections ([ProxySQL](https://proxysql.com/))
    3. If ACID is not required, set [innodb\_flush\_log\_at\_trx\_commit = 2](https://dba.stackexchange.com/questions/12611/is-it-safe-to-use-innodb-flush-log-at-trx-commit-2)
    4. Remove unnecessary indices. Indices slow down write operations.
    5. Avoid bulk insert/update operations since they block the database.
    6. SELECT only required fields in your queries. Avoid selecting fields (especially TEXT/BLOB fields) if they are not included in the used index.
    7. Move TEXT/BLOB fields to a new table if they are not always accessed.

    # Redis

    1. Avoid using `database` option in Laravel configuration
    2. Use a connection pool ([Twemproxy](https://github.com/twitter/twemproxy))

    # PHP/Laravel

    1. [Make sure PHP opcache is on and configured properly](https://tideways.com/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises)
    2. [Make sure PHP-FPM is configured properly](https://tideways.com/profiler/blog/an-introduction-to-php-fpm-tuning)
    3. [Preload php scripts](https://stitcher.io/blog/preloading-in-php-74) (You need to update to PHP 7.4 at least)
    4. [Cache Laravel routes](https://laravel.com/docs/8.x/routing#route-caching) (php artisan route:cache)
    5. [Cache Laravel configuration](https://laravel.com/docs/8.x/configuration#configuration-caching) (php artisan config:cache)
    6. [Cache Laravel views](https://laravel.com/docs/8.x/views#optimizing-views) (php artisan view:cache)
    7. Move as many operations as possible to queues. Keep only essential operations in web requests.
    8. Store queued jobs in Beanstalkd if possible. If you want to use Redis, use a dedicated Redis server, not a database in the same Redis instance. Avoid using database driver.
    9. Do not mix web and worker instances. Do not process queue on web servers.
    10. “[You should also try and make queues for different things.](https://www.reddit.com/r/laravel/comments/kd3n1q/im_scaling_our_startup_using_laravelphp_to_half_a/gfwz27f/)” (thanks to [/u/slyfoxy12](https://www.reddit.com/user/slyfoxy12/))
    11. Move sessions to Redis

    # Web server

    1. [Compress responses](http://nginx.org/en/docs/http/ngx_http_gzip_module.html)
    2. [Use HTTP caching where possible](http://nginx.org/en/docs/http/ngx_http_headers_module.html)
    3. Serve assets from CDN

    Reply
  23. Obvious answer here is redis caching, however to start with you could look at database load and determine your most demanding select statements. Then go in order and decide how up-to-date that data needs to be (in your case even caching for 5 mins will really help) and that will reduce your db load while making your service seem snappier and more responsive.

    Of course there is always the cloud route if on-prem fails (or becomes too expensive) and having one or more read replicas in each dominant region.

    On another note if you don’t already you should use a CDN, which is an easy way to remove the majority of static asset requests from hitting your servers. Even a good nginx configuration will help as it will tell browsers to cache your content.

    Reply
  24. There is Session and then there is cache.

    Items which constantly change are normally not a good candidate for caching.

    **Cache**

    \- Cache is for storing and retrieval of information that will be both static and the same for all Users. Items such as Lookup lists are great candidates for cache. It is pretty stunning what can be stored in cache. As stated by others. not everything should be cached. I currently use cache for:

    1) ALL reference data. The reference data is pretty darn static and is the same for all Users.

    a) You can put all the reference data in one view which is cached or each reference table or grouping can be cached separately. Completely up to you and depends upon your wants/needs. I currently have about 5-6 different reference table caches due to the data’s groupings.

    2) Labels that are used in almost every Form such as: the wording for the CRUD actions, and the Create/Save/Cancel/Delete button wording, etc.

    3) If you are doing reporting on previous periods, the data normally will not change. I thought this was a brilliant use of cache. This saved hits on the database and allowed for the data to be accessed in less time.

    **Session**

    \- Session data is specific to a User and not shared amongst Users. I currently use Session data for:

    1) Retaining the Users Name, Birthdate, and some other misc items. But the use is very very limited.

    I originally used Session for everything mentioned above until I discovered that I took the wrong approach and was negatively affecting the User’s experience (it was taking up too much memory). It took me a few weeks to correct this but the result was well worth the time.

    Reply
  25. Find out what is slowing your services down. Newrelic isn’t cheap if you run it everywhere, but typically affordable and very good onone server for this sort of thing. Find the bottlenecks.

    What do you mean by “consuming heavy loads” while also saying “long running scripts have been eliminated?”. It doesn’t sound like it.

    What is slowing things down? If you don’t know then no wonder you don’t have a caching strategy.

    What does “performance is fine” mean when you’re complaining it’s slow? What does “2000 reqs/sec handled by 8x 40 cores (more then enough)” Do you know your average response time? If it’s high then it may not really be enough. It just might seem like it because you don’t know the actual performance and you don’t know what’s actually making it slow.

    Reply
  26. Some great tips in this thread, would love to know how you end up solving your issues.

    I would start with installing something that can give you a high level overview of bottlenecks, then drill into each one and identify what needs to be fixed.

    Have used New Relic but much prefer DataDog.

    1-2 seconds is pretty slow for DB queries for basic selects and a few joins. Are you doing a lot of joins or are your queries super complex?

    Definitely get a CDN to serve static assets, they should be compressed into 1 file for JS and 1 for CSS. gzipping helps too, something CDNs generally offer.

    Lighthouse tool in Chrome is really useful for analysing frontend issues, could be worth double checking those, especially if they relate to something that could affect your servers, e.g. large assets

    Reply
  27. Redis there but not used? Start with session storage. You using a CDN? Is HA proxy caching any files for you. It goes like this:

    Step 1 – Tune your application, application server and database server to be as fast as possible. Opcache/APC. Database sizing, webserver tuning.

    Step 2 – Do everything you can to avoid hitting your database and application server. Redis, cdn, varnish (or another caching proxy)

    Step 3 – add scaling (multiple application servers, database replication)

    Reply
  28. Did you mean NFS storage? Are you sure your file writing classes aren’t blocking on your shared storage?Does your HA proxy correctly track individual connections ( do you have something like sticky sessions to guarantee than your distribution logic sticks?)Are you using one central database OR syncing them using federated data tables?Redis may not even be the right answer, it depends on what you are using. If you are overloading all your databases, maybe install laravel scout with elastic search sync your models that way for slow-lookups. This will at the very least buy you a ton of time for the least amount of work possible if your issues are related to slow queries).

    Feel free to message me if you need this figured out, im sure i can do it in a few hours tops.

    Reply
  29. No caching at all? Yikes! All static assets for one should be hosted on a CDN. I would use the Redis layer to cache sessions and share state if your HAP is not doing sticky sessions yet. You can also use Redis to possibly do some level of query caching to take the load off of your DB, or at least decrease the hits in a time frame.

    Reply
  30. Make sure you aren’t storing configuration in yaml files. It really kills your performance (unless you serialize the result to file).

    Reply
  31. Install New Relic and understand quickly where you bottlenecks are.

    You have then 2 options, optimise code or improve & optimise infrastructure.

    Laravel vapor might give you a quick win on auto scaling.

    Do some testing with load test when you make changes to ensure it improves what you think rather than waiting to see improvements on production.

    Or hire a dev ops person?

    Awesome job on the scaling, dev ops is easy vs that so congratulations.

    Pa what’s the app?

    Reply
  32. I’m curious to hear what kind of software architecture you’re using? Is this app built using the default Laravel architecture? Are you using something like event sourcing?

    Reply
  33. For the last couple of days I’ve been working on the performance of a Laravel app. Clockwork ([https://github.com/itsgoingd/clockwork](https://github.com/itsgoingd/clockwork)) has been such a great help! Please check it out. It will show:

    * all your queries including the time they take;
    * all your cache hits and misses;
    * a timeline with queries and controller actions so you see what php code takes long
    * performance issues (like N+1 queries).

    There is a lot more to it, but these have been very helpful to me personally.

    Reply
  34. As well as using slow logs to look for db query optimizations, I’d highly recommend setting up an event listener on your db queries which counts number of queries per request, and if that exceeds a certain threshold (eg. 30 queries), log the endpoint and come back to it locally to investigate any potential n+1 query problems which can arise from poor model design (queries inside attribute accessor methods / appending relations etc) or poorly written controller/service code (not eager loading where you should etc)

    Reply
  35. The first and most important thing to realize is every app is different. You will never find a silver bullet. The first thing you need to do is identify exactly where the problems exist. I suggest using some sort of monitoring. I use Zabbix for all my stuff and have it running on a $20/month Linode. It really saves a lot of time and headache when nailing down problems, plus it’s very easy to write new data collectors for custom things inside your app.

    Until you identify the actual problem and what is causing it, you’re just throwing darts blindfolded.

    In combination with the above, also duplicate your setup on a smaller scale (1 node and no HAProxy). Get a real benchmarking system (not AB) to test it out. I always use JMeter. Setup several test plans that mimic various ways users interact with your site (registering, logging in, posting, purchasing, etc.). Run your tests while monitoring. Fix whatever problems you identify, then run your tests again. We rely on JMeter so much that we include test plans in all our repositories (or in a special “infrastructure” repository for that client).

    One thing I will say on caching is it’s a good thing to have, but can easily be abused/misused. You need to heavily consider your caching implementation. A lot of people simple think they can run a query that takes a second or more, then do a Cache::set and that will fix everything. Chances are it will be fine in most cases, but in high traffic scenarios, what if you have 4 or 5 people hitting that same request in that 1 second? You’re starting to get a bottleneck. So for caching expensive processes, don’t do on-demand caching. Cache it when the data changes, and preferably through a worker.

    Reply
  36. Can you let us know once you have figured it out?

    one gotcha is when u increase the size of server, you need to tinker with ‘children’ settings in php.ini otherwise PHP wont take any notice of increased speed.

    The other thing I would do is, try using Vapor to see if that would work for you? its fairly easy to set up.. YML file is easy to write to.. You just need to tinker with how many lambdas you need to have ‘constantly running’ depending on your traffic.

    Reply
  37. > und multiple self provisioned NGINX/FPM containers

    My largest app is like 99% api and 1% ui – so caching didn’t really solve my problems. I will say this though – if you’re doing a lot of server side processing (as opposed to DB side processing) then I would recommend looking at solutions like Google App Engine that automatically scale and load balance in a “serverless” environment

    The only hurdles are: moving all of your storage operations (sessions, files, cache) to either the db or to their cloud storage. Basically you just treat it as an external disk

    Other biggest learning curve is the permissions but that’s a small one

    Reply
  38. What version of PHP are you using?

    Does that PHP version have enabled OPCache in php.ini?

    Since prestashop (whenever its good or not) is also a PHP application you may find some of the settings here [https://devdocs.prestashop.com/1.7/scale/optimizations/](https://devdocs.prestashop.com/1.7/scale/optimizations/) suitable for scaling.

    Remove any extensions like xdebug / pcov / debugging modules from the php environment you are using in production.

    Reply
  39. This is really interesting to read. I’m following along as we’re having some growing pains as well. Currently in the process of migrating from EC2 to Fargate and I’ve been reading a lot of documentation to get the best out of both nginx and PHP-FPM.

    Reply

Leave a Comment