Then, for app performance:
My approach is to usually design the app / refactor the app so static content can be fully cached. In ecommerce sites this can make an absolutely impressive difference. Then, leverage opcache and object cache and further separate cacheable path from dynamic path in dynamic SSR queries. Always drive using APM performance metrics as a guide. No need to optimize the DELETE /user endpoint called twice a week.
Then, identify the heavy hitters in the dynamic DB queries, and basically write those in hand rolled SQL. It usually boils down to 4 or 5 queries doing 99% of the work (GET /posts, GET /categories, GET /products, etc...). I do this fairly late in the game, but think about it very hard up front. I like to use some kind of ORM for everything writing to the DB, and sql builders / pure SQL for reading.
The split between cacheable / non-cacheable can be subtle depending on the application, and might require some non-obvious structures in the codebase.
For real tricky performance issues (not something I had to do in PHP projects), I will either ducttape some AWS infrastructure or handroll a microservice in C++ or golang. This is something I had to do for realtime / transient loads.
It doesn't make scaling hard, it makes scaling very easy because you can just horizontally scale out as many instances as you need. The constant factor is pretty awful, but that's the tradeoff you make for statelessness.
In practice it makes scaling hard for financial reasons if you require 128MB+ per request. A 32GB server will struggle with more than 256 concurrent requests at 128MB+ per request. A 32GB server is an extremely large server for such low request numbers.
If you can bring the memory usage down stateless works well. I use a bit of rust on aws lambda with the lowest memory settings so pay fractions of a cent and can handle more traffic than I ever need. I do set up persistent connection pools for the life of the lambda and only bootstrap once to bring down latency per-request but treat it as an ephemeral horizontal scaled service.
With that said, I think the stateless nature of php is talked up too much.
While not enforced by the nature of the language like php, writing stateless apps in other languages comes quite naturally.
Scaling difficulties are almost always to do with the database solution rather than the app, and overcoming those problems has little to do with the choice of language.
I of course value at least partial "stateless" (functional core / hexagonal architecture, event driven architecture) in any language, because they reduce complexity so much.
In Laravel it's not too hard to avoid this problem but a lot of noobs don't get the lazy / eager loading thing and then you end up like this.
Drupal seems to add hundreds of queries for every module you add.
I do think very hard up front what the product will require in terms of: - static content - dynamic content that is cacheable and which keys can be used to cache it
Static content can use ORM as much as it wants, cloudfront will take care of it. dynamic content that is rarely hit doesn't really need much help either if there are no UX latency requirements. dynamic content that is hit very often (usually only a couple of endpoints) can be rewritten into manual SQL.
If you think about it, most page hits with dynamic content can be rendered basically by the DB + templating engine, and no other logic should be involved.
I noticed being stateless made it difficult to scale for any complex app. It’s been 7-10 years since I used it but Drupal used 60-128MB+ plus per request. As it was stateless it had to do a full bootstrap for every request coming in, set up a new database connection, module discovery etc, all which was heavy to do for every request. Most people scaled Drupal by putting Varnish in front preventing the origin from being hit so not really scaling Drupal as such, varnish is taking off some load where it can.
Drupal is probably the extreme though. If you have a simple app with a few scripts, light use of a DB it’s not to bad. I’ve heard it’s come on a lot in the past 10 years and Laravel. I certainly had less issues using PHP than I do with JavaScript.