Backend Performance - Identify and Solve Problems!

Are you having performance issues with your application? Let's take a look at the performance tuning options. Let's talk about programming languages, caching, databases, and scaling.

Wer nichts wagt, kann auch nichts gewinnen!

Marco Schiffmann
packt jede Gelegenheiten am Schopf und scheut sich nicht vor neuen Herausforderungen
Logoteppich: JS, php, R, MySQL, MariaDB, PostgreSQL
Reading duration: approx. 6 Minutes

We've already covered the topic of front-end performance . This article focuses on performance in the Backend and the factors that play a role in application development. What needs to be considered, and what options are available for optimization?

Calculating Pi Using the Leibniz Formula. Performance: Rust, JS, PHP

Languages - PHP, JS, Rust...

Even when choosing a programming language as the basis for developing an application within a project, there are significant differences in performance.

Looking at the raw numbers—for example, when calculating the “Leibniz formula” to approximate pi—it becomes clear that languages like PHP, which we use in many of our projects, are at a distinct disadvantage compared to JS or Rust. In this case, the calculation for pi using the Leibniz formula was iterated 1,000,000,000 times. (Source: GitHub, Niklas Heer)

It is therefore important to seriously consider the application’s requirements at the start of a project. In addition to raw computing power, many other factors naturally play a role in the selection process.

For example, Rust would be a good choice if the application is safety-critical (memory and type safety), scalability is a factor (multithreading), or low-level programming is essential. These are all areas where PHP performs less well.

For many client projects, PHP stands out thanks to a wide selection of established frameworks (Laravel, Symfony, etc .), easy hosting, faster development and debugging, and a more dynamic approach to typing.

In our experience, it pays to conduct a thorough analysis of the application’s objectives at the start of the project in order to take advantage of speed benefits through the choice of programming language, if possible, right from the outset.

In practice, however, other factors are more significant for Backend performance in our project work.

Logos: Rust, PHP, JS
Programmers waste an enormous amount of time thinking about—or worrying about—the speed of noncritical parts of their programs, and these attempts at efficiency actually have a significant negative impact when debugging and maintenance are taken into account. We should ignore minor efficiency gains about 97% of the time: premature optimization is the root of all evil. Yet we should not overlook opportunities in that critical 3%.
Knuth, D. E. (1974). “Structured Programming with go-to Statements,” ACM Computing Surveys, 6(4), 261–301.

Peripheral Systems

Of course, to assess the overall performance of an application, it is important to consider the infrastructure and peripheral systems in which it is embedded. Many components influence performance. It is essential to examine the interaction between databases, caches, file storage, and interfaces. Based on our project experience, this interaction offers significant potential for optimizing an application’s performance.

But how do we proceed, and where do we start, without wasting valuable project resources on minor performance gains?

System Overview: Development

Identifying areas for optimization? Where do we start?

How can we identify and narrow down the actual optimization needs of our application so as to waste as few resources as possible on non-critical optimizations? This question comes up again and again in day-to-day project work.


Blackfire & Nginx logs

A good example of a tool in this area is "blackfire," which we are currently evaluating for our PHP projects. Through continuous profiling, live monitoring, testing, and CI/CD integration, the software can quickly identify bottlenecks and visualize them for our developers. It remains to be seen to what extent we will integrate the software into our existing CI/CD processes.

Another “tool”—or rather, a good indicator—that we’ve been using in our projects for some time is the analysis of the Varnish cache status from the Nginx logs .

We look at which content is successfully cached and which is not (miss, uncacheable, unconfigured) and monitor any deviations. “Clustering” the content types from the Nginx log by “request time” also provides initial insights into the causes of performance issues in the application.

balackfire.io, nginx logo

Caching

A well-designed caching system that distinguishes between different cache units delivers a direct performance gain with moderate effort. There are a number of cache units into which caching can be divided. The most important ones are “object caches” and “full-page caches,” though there are, of course, also query caches, opcode caches, and many others.

It may sound trivial, but in practice, our projects have shown that it’s worth taking the time to do this—and distinguishing between dynamic and static content isn’t always easy for our clients. But the analysis is worth the effort to realize performance gains.

Redis, Memcached logo

"Object Caches"

These caches are suitable for complex, deterministic operations as part of application routines, such as dynamic web applications with personalized content or dynamic data. Since the request is retrieved from the cache, this reduces the load on the database and APIs. Redis, Memcached, or APCu are frequently used for this purpose.

"Full Page Caches" (FPC)

With "Full Page Caches" (FPC), as the name suggests, fully rendered pages (HTML, CSS, JavaScript) are cached and served directly, which significantly reduces the load on the web server and the database. This type of caching is perfect for static content, but it also has its drawbacks, as changes—for example, those made by the editorial team—can cause delays because the cache must first be updated. FPC works exclusively with "GET" requests.

Varnish, Nginx, or Fastly are frequently used for this purpose. In addition to improved performance, the cache in this case also protects against success or DOS issues, since the web server is not accessed directly.


Databases

To avoid performance issues, it makes sense to use relational databases (RDBs) such as MySQL, PostgreSQL, or MariaDB. Of course, for each application, you must determine whether to use relational or non-relational databases; in traditional CMS, CRM, or e-commerce environments, relational databases are often the preferred choice.

The advantages of RDBs are obvious: their tabular structure allows queries to be executed efficiently. Queries run even faster when “indexes” are defined. However, it’s important to note that even minor changes to the database require the index to be rebuilt, which can also take time. The goal is to shift the logic to the database, which is best suited for this task and can process it very efficiently. If performance issues are detected in the database, a pragmatic solution may simply be to increase the available memory.

Without wasting resources unnecessarily—for example, on code optimization—significant performance gains can already be achieved on the query and database sides.

MariaDB, PostgreSQL, MySQL database logos

Scaling

Vertical and horizontal scaling are classic methods for improving performance. Both methods have their advantages and disadvantages, but they have a significant impact on performance and should be examined more closely when problems arise.

Vertical Scaling vs. Horizontal Scaling: A Chart

Vertical Scaling (Scale-Up)

Vertical scaling (scale-up) is based on increasing performance through hardware upgrades. Additional CPU and RAM capacity is provided to execute operations more quickly.

The advantages are that this method is easy to implement and causes virtually no additional latency (e.g., network overhead). It also does not introduce additional complexity through extra software, since the optimization takes place on the hardware side.

A clear disadvantage, of course, is the physical limitations of the hardware and the risk of failure. Furthermore, it can be costly to maintain a high-performance server rather than falling back on multiple small instances (horizontal scaling).

Horizontal Scaling (Scale-Out)

Horizontal scaling (scale-out) aims to avoid relying on a single high-performance server and instead distribute an application’s load across multiple servers. This approach relies on a microservices architecture, which can be combined with load balancers, for example, and also includes database sharding and container orchestration.

The advantages include incredibly flexible scalability—allowing new instances to be easily added—and ensuring high reliability. Dynamic scaling with Kubernetes or Auto Scaling Groups also offers many benefits for dynamic applications.

A clear disadvantage is the complexity of the system, which increases with every additional component. The requirements for synchronization and consistency (consistency management) increase, and more database and network overhead (network communication, data replication) is generated. In particular, applications based on relational databases are not suitable for horizontal scaling.


Conclusion

There are many factors you can adjust to improve an application’s performance. Even though you can avoid typical problems right from the design phase of an application— such as in the architecture and infrastructure, the choice of programming language, and the right scaling approach, it’s important not to start optimizing too early and to take the time to analyze the system so as not to waste a lot of resources on minor performance gains. Using “blackfire” and the nginx logs, we’ve highlighted two ways to identify problems and examined classic areas such as caching and offloading logic to databases.

Especially in large projects with many dependencies, it is often not easy to identify the causes of performance issues. This article is intended to help you get started in finding the causes and, if possible, prevent them from arising in the first place.

If you’re unable to find the cause of performance issues in your application, we’d be happy to assist you with our experience from over 25 years of application development.

Marco Schiffmann at the computer
Having performance issues with your application?
If your application isn't performing well, we'd be happy to help. Just contact us!
Marco Schiffmann
Digital Consultant
+49(0)721 91090
Contact now
Share:

More articles

challenge accepted
Maik Peuser, Entwicklung at punkt.de
Working at punkt.de