Synthetic Monitoring

Simulate visitor interaction with your site to monitor the end user experience.

View Product Info

FEATURES

Simulate visitor interaction

Identify bottlenecks and speed up your website.

Learn More

Real User Monitoring

Enhance your site performance with data from actual site visitors

View Product Info

FEATURES

Real user insights in real time

Know how your site or web app is performing with real user insights

Learn More

Infrastructure Monitoring Powered by SolarWinds AppOptics

Instant visibility into servers, virtual hosts, and containerized environments

View Infrastructure Monitoring Info
Comprehensive set of turnkey infrastructure integrations

Including dozens of AWS and Azure services, container orchestrations like Docker and Kubernetes, and more 

Learn More

Application Performance Monitoring Powered by SolarWinds AppOptics

Comprehensive, full-stack visibility, and troubleshooting

View Application Performance Monitoring Info
Complete visibility into application issues

Pinpoint the root cause down to a poor-performing line of code

Learn More

Log Management and Analytics Powered by SolarWinds Loggly

Integrated, cost-effective, hosted, and scalable full-stack, multi-source log management

 View Log Management and Analytics Info
Collect, search, and analyze log data

Quickly jump into the relevant logs to accelerate troubleshooting

Learn More

Optimizing Load Times on Apache Web Server on Digital Ocean With SolarWinds Pingdom

Introduction

We all want the fastest application possible for our customers. At the same time, we’re under pressure to continuously add new features. These new features add complexity, which makes our application heavier, which in turn slows our applications down. 

So, how do we add new features, yet keep the performance of our application high?

In this article, we’ll look at how you can achieve fast speeds by using SolarWinds® Pingdom® to optimize Apache web server on DigitalOcean. DigitalOcean is the perfect solution to launch and scale your application—it provides fast connections, worldwide data centers, and easy control of deployments. And Pingdom is the ideal addition to DigitalOcean for measuring and optimizing our website speed. Together, they provide the perfect solution for fast, scalable, and reliable applications.

Let’s start by setting up a sample website on DigitalOcean using Apache and WordPress (to simulate our web application). Then we’ll walk through how to measure and improve our site speed using Pingdom. If you already have a website, you can skip the setup and start from the “How to Understand Your Website’s Speed” section.

Creating Your Droplet

First, we need to create our Droplet on DigitalOcean. This is simple and takes just a few steps.

For our example, let’s choose an Ubuntu 20.04 image and the most basic plans for our Droplet.

Next, select the closest location to your targeted audience and any additional options.

For authentication, we’ll select SSH Keys (as they’re more secure). If you don’t have a key, just create one using the DigitalOcean tutorial shown after you click “New SSH Key.”

Finally, click the “Create Droplet” button.

We can now see our public IP on the right side of the hostname.

Setting up Your Applications Now that the Droplet is created, we need to update the package index, upgrade outdated packages, and install Apache and any required packages for our simple WordPress application.

apt-get update && \
apt-get upgrade && \
apt-get install -y && \
	apache2 \
	php7.4 \
	php7.4-mysql \
	mysql-server \

To quickly verify the web server is responsive, you can browse to your droplet’s IP:

http://<droplet-external-ip>/

Creating the MySQL Database and User

Next, let’s create a small database for our application. Use the “mysql” utility to create a MySQL shell.

mysql

You should see something similar to the following:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 24
Server version: 8.0.22-0ubuntu0.20.04.2 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

Now create the database with the “CREATE DATABASE” command.

mysql> CREATE DATABASE mywordpress;

Query OK, 1 row affected (0.01 sec)

Create your user using “CREATE USER.”

mysql> CREATE USER "mywordpressuser"@"localhost" IDENTIFIED BY "Duc90okpwmFaN8VYhA8n2M";

Query OK, 0 rows affected (0.01 sec)

Grant the necessary privileges to the created user.

mysql> GRANT ALL PRIVILEGES ON mywordpress.* TO "mywordpressuser"@"localhost";

Query OK, 0 rows affected (0.01 sec)

Flush the privileges.

mysql> FLUSH PRIVILEGES;

Query OK, 0 rows affected (0.01 sec)

Now exit the shell.

mysql> exit

Bye

Installing WordPress

For the last step, we need to install WordPress. Change the current directory to the Apache default document root.

cd /var/www/html/

Download the latest WordPress files.

wget https://wordpress.org/latest.tar.gz

Extract the files to the current directory.

tar -xzv --strip-components 1 -f latest.tar.gz

Remove the archive.

rm latest.tar.gz

Copy sample wp-config,php, so we can edit the configuration.

cp wp-config-sample.php wp-config.php

Open wp-config.php with your favorite editor.

nano wp-config.php

To finish, change a few values you set earlier in the MySQL section: 

  • DB_NAME
  • DB_USER
  • DB_PASSWORD

Also be sure to update the following (you can generate new unique phrases using this link https://api.wordpress.org/secret-key/1.1/salt/):

  • AUTH_KEY
  • SECURE_AUTH_KEY
  • LOGGED_IN_KEY
  • NONCE_KEY
  • AUTH_SALT
  • SECURE_AUTH_SALT
  • LOGGED_IN_SALT
  • NONCE_SALT 

How to Understand Your Application’s Speed

With our application set up, we’re ready to get started! Let’s look first at understanding your application’s speed. 

An application’s speed can be affected by many different aspects such as back-end functions, database connection and queries, page sizes, component sizes, external requests, and so on. The total time for your page to load is the sum of these different aspects. Here’s a typical timeline with the different stages:

Timeline TermDescription
DNSHow long it took for the DNS query
SSLTime passed for SSL negotiations
ConnectTime to connect
SendTime elapsed while sending the request data
WaitTime to wait for the remote side
ReceiveTime elapsed while receiving the response data
First byte receivedWhen the first byte is received
DOM content loadedPage components loaded
On loadPage fully loaded, run scripts and ready for viewing

For this portion of the article, we’re going to focus on the broader “On load” time.

For more information, please see How to Analyze Website Speed Test Results and A Beginner’s Guide to Web Performance.

Introduction to Pingdom

Now let’s look at SolarWinds Pingdom and how it can help you speed up your Apache web server.

First, create an account. Once you’ve created an account, the Pingdom main page will show you several recommended monitoring options. Please refer to the Getting Started With Pingdom guide for detailed information on each feature.

We’ll focus on the “Page Speed” check. Click that option.

Setting a Baseline With Pingdom

To start monitoring, fill out the requested information on the next screen:

Select the closest location based on your site’s location in “Test from” field. Once your check is created, give Pingdom a few minutes to create your first report. Once the report is ready, click the report link under the “Latest tests” list. This “default” speed of our application, without any tweaks, is going to be the baseline data we work from. 

With this initial report, Pingdom also gives us a lot of information we can use to improve our website’s speed. At the top of the report, you’ll see a few statistics for your page: “Performance Grade,” “Load time,” “Page size,” and number of “Requests.” 

You’ll also see Performance Grade Details, a built-in smart analysis showing you ways to improve your site speed. For example, here you see “Use CDN” and “Add Expires headers.” Using a Content Delivery Network (CDN), for example, can dramatically increase your web application’s speed. (For more information about CDN please see A Beginner’s Guide to Using CDNs.)

In this view, you’ll also see content size and requests by content type.

You’ll also see content size and requests by domain. This information can show us if one or more of our resources is being loaded from an external site, which could affect performance.

One of the most important views is “Timeline.” This view displays a timeline of the requests. Various metrics appear in alignment with each file loaded. This can help us identify trouble spots.

We can also dig deeper and see the details of each file. Here, request and response headers are shown.

With this information, we can see “content-encoding” is already using gzip. This means Apache is already compressing components by its default configuration.

Optimizing Apache

Now that Pingdom is set up and monitoring our website, let’s look at a few ways—based on the reports above—we can configure Apache to improve our load times. We’ll use Pingdom to confirm our changes have helped. Using their page speed analysis toolsets, we can clearly see and finely tune these settings to fit our needs. There are a seemingly infinite number of knobs to turn, but we’ll use some best practices, and use Pingdom metrics to judge our success.

We’re going to use three modules to fine-tune our website: Expires, Headers, and Deflate. Using those modules, we will:

  • Enable Compression
  • Enable Browser Caching
  • Disable “.htaccess” Lookup
  • Disable DNS Lookups
  • Enable and Configure Keepalive
  • Enable HTTP/2

First, make sure all three modules are enabled.

a2enmod expires headers deflate

The response shows us expires and headers modules are now enabled, and deflate was already enabled.

Enabling module expires.
Enabling module headers.
Considering dependency filter for deflate:
Module filter already enabled
Module deflate already enabled
To activate the new configuration, you need to run:  systemctl restart apache2

Now restart the Apache2 service to apply the new module configurations.

systemctl restart apache2

Enabling Compression

Let’s start with compression. The deflate module is Apache’s compression/decompression module. It compresses the output files, decreasing the number of bytes that need to be transferred to the client. However, while this lowers network bandwidth and drastically reduces load time, be aware it also uses CPU cycles. If your server’s CPU is already highly utilized, compression might affect performance adversely—the opposite of what we’re trying to do! A useful article to read on this topic is Measuring the Performance Effects of mpd_deflate in Apache.

Although compression is enabled by default, the default configuration has limited types enabled. By using the AddOutputFilterByType directive, we can define which MIME types will be compressed.

Let’s update the file:

nano /etc/apache2/sites-available/000-default.conf

Paste the following snippet into the file.

 <IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE application/javascript text/javascript application/x-javascript text/js  
  AddOutputFilterByType DEFLATE application/xhtml+xml application/xml text/xml application/rss+xml  
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject  
  AddOutputFilterByType DEFLATE application/x-font application/x-font-opentype application/x-font-truetype  
  AddOutputFilterByType DEFLATE application/x-font-ttf font/opentype font/otf font/ttf  
  AddOutputFilterByType DEFLATE image/x-icon image/svg+xml   
  AddOutputFilterByType DEFLATE text/css text/html text/plain
</IfModule>

Now reload Apache to apply the configuration changes.

systemctl reload apache2

Enabling Browser Caching

Next, let’s enable browser caching. Although it doesn’t change the actual loading times of the page, browser caching drastically improves the user experience by indicating which components can be cached in the browser for subsequent requests.

Be aware, however, high cache expires headers, while excellent for the user experience, can cause updated versions of resources to not be used. If this is the case for your deployment, consider a build process to rename the file (timestamp, MD5 hash, etc.), so newer versions of the file are always reloaded.

Here, we’ll configure a default of five days and one month for the below file types. You’ll need to apply the configuration by modifying the expires time according to change frequency and build process.

Go ahead and edit the file:

nano /etc/apache2/sites-available/000-default.conf

Paste the following configuration between <VirtualHost *:80></VirtualHost> tags.

<IfModule mod_expires.c>
    ExpiresActive on    
    ExpiresDefault "access plus 5 days"    
    ExpiresByType text/js "access plus 1 months"    
    ExpiresByType text/javascript "access plus 1 months"    
    ExpiresByType application/javascript "access plus 1 months"    
    ExpiresByType application/x-javascript "access plus 1 months"    
    ExpiresByType application/xhtml+xml "access plus 1 months"    
    ExpiresByType application/xml "access plus 1 months"    
    ExpiresByType text/xml "access plus 1 months"    
    ExpiresByType application/rss+xml "access plus 1 months"    
    ExpiresByType application/vnd.ms-fontobject "access plus 1 months"    
    ExpiresByType application/x-font "access plus 1 months"    
    ExpiresByType application/x-font-opentype "access plus 1 months"    
    ExpiresByType application/x-font-truetype "access plus 1 months"    
    ExpiresByType application/x-font-ttf "access plus 1 months"    
    ExpiresByType font/opentype "access plus 1 months"    
    ExpiresByType font/otf "access plus 1 months"    
    ExpiresByType font/ttf "access plus 1 months"    
    ExpiresByType text/css "access plus 1 months"    
    ExpiresByType text/html "access plus 1 months"    
    ExpiresByType text/plain "access plus 1 months"    
    ExpiresByType image/gif "access plus 1 months"    
    ExpiresByType image/jpg "access plus 1 months"    
    ExpiresByType image/jpeg "access plus 1 months"    
    ExpiresByType image/png "access plus 1 months"    
    ExpiresByType image/x-icon "access plus 1 months"    
    ExpiresByType image/svg+xml "access plus 1 months"
</IfModule>

Disable “.htaccess” Lookup

Apache has a configuration override feature giving you the ability to modify configuration per-directory using the .htaccess file. As these changes don’t require a reload, they can be perfect for operations teams to customize behaviors. By default, Apache looks for a .htaccess file to see if any override configuration exists on each page lookup. However, if you don’t require .htaccess functionality, you should disable the lookup. You can still use the same directives on virtual host configuration.

Edit the file:

nano /etc/apache2/sites-available/000-default.conf

Inside the <VirtualHost *:80></VirtualHost>, paste the following to disable the .htaccess file in each lookup.

<Directory />
    AllowOverride none
</Directory>

Disable DNS Lookups

The HostnameLookups directive provides DNS resolution for the IP addresses in the logs. Each time a client makes a request, a DNS request is sent. If you aren’t using the hostname as a reference, you can disable this lookup to increase performance.

Edit the file:

nano /etc/apache2/apache2.conf

Find “HostnameLookups” option and make sure it’s “Off.”

HostnameLookups Off 

Save/exit and reload Apache for the configuration to take effect.

systemctl reload apache2

Enabling and Configuring Keepalive

The Keepalive feature allows HTTP/1.0 clients to use a persistent connection to send multiple requests. This persistent connection reduces the connection time for each request. However, this feature can allow dead connections to remain open, so be sure to use a reasonable timeout value.

Configuring the Keepalive feature is straightforward. After enabling with On, there are two parameters you can configure. MaxKeepAliveRequests determines how many requests can be sent through a KeepAlive connection. KeepAliveTimeout determines how many seconds the server should wait between requests.

In the file:

nano /etc/apache2/apache2.conf

Edit these settings:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

Reload the Apache service for changes to take effect.

systemctl reload apache2

Enabling HTTP/2

HTTP/2 is the most recent version of the HTTP protocol (HTTP/3 is on its way at the time of this writing). HTTP/2 has greatly improved page load times. Before HTTP/2, components were transferred sequentially over individual connections. Now, transfers rely on a binary protocol supporting multiple requests/responses (called streams) over the same connection. This reduces the time it takes to establish multiple connections to the server and improves the overall network latency. HTTP/2 can also push data before the client asks for it. 

Let’s enable http2 module.

a2enmod http2

An output similar to the one below is displayed.

Enabling module http2.
To activate the new configuration, you need to run:  systemctl restart apache2
systemctl restart apache2

Response Headers

Finally, let’s check the response headers to ensure our configurations are correct and Apache is behaving as it should. Use curl command to get request and response headers.

curl -v -s --http2-prior-knowledge -D - -o /dev/null http://localhost

Here, we can see we initiate the connection via HTTP/2 protocol and server response is as it should be. We can also see expires headers as well.

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5631d29067c0)
> GET / HTTP/2
> Host: localhost
> user-agent: curl/7.68.0
> accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200 HTTP/2 200 
< date: Fri, 30 Oct 2020 10:56:08 GMT
date: Fri, 30 Oct 2020 10:56:08 GMT
< server: Apache/2.4.41 (Ubuntu)
server: Apache/2.4.41 (Ubuntu)
< x-trace: 2B04C15ED9A7A6B279ED6CD3CD3E1BE84E8FC6AF135355ABF6E97E296201
x-trace: 2B04C15ED9A7A6B279ED6CD3CD3E1BE84E8FC6AF135355ABF6E97E296201
< link: <http://159.65.123.126/index.php/wp-json/>; rel="https://api.w.org/"
link: <http://159.65.123.126/index.php/wp-json/>; rel="https://api.w.org/"
< cache-control: max-age=2592000
cache-control: max-age=2592000
< expires: Sun, 29 Nov 2020 10:56:08 GMT
expires: Sun, 29 Nov 2020 10:56:08 GMT
< vary: Accept-Encoding
vary: Accept-Encoding
< content-type: text/html; charset=UTF-8
content-type: text/html; charset=UTF-8

Observing Improvements With Pingdom

Now let’s use SolarWinds Pingdom to check the improvements our changes have made.

We can see web application’s “Performance grade” (YSlow score) has increased from 83/100 to 92/100. We’ve gone from a B to an A!

We can also see the improvements from the baseline.

In the detail section of this CSS file, we can see a few of our improvements in action. The content encoding is “gzip,” the response headers include the expires header we set, the connection uses Keepalives, and HTTP/2 is enabled.

Conclusion

In this article, we deployed a simple website using Apache and DigitalOcean, then used Pingdom to measure and create a baseline of our site’s speed. We then used the suggestions and measurements from SolarWinds Pingdom to enable a few optimizations on Apache and saw the speed improvements in action. Using Pingdom in combination with Digital Ocean gives teams the perfect way to deploy, scale, and improve our applications.

Be sure to check out the 30-day free trial of Pingdom and experience how it helps you measure, analyze, and improve load times.

Webpages Are Getting Larger Every Year, and Here’s Why it Matters

Last updated: February 29, 2024 Average size of a webpage matters because it [...]

A Beginner’s Guide to Using CDNs

Last updated: February 28, 2024 Websites have become larger and more complex [...]

The Five Most Common HTTP Errors According to Google

Last updated: February 28, 2024 Sometimes when you try to visit a web page, [...]

Page Load Time vs. Response Time – What Is the Difference?

Last updated: February 28, 2024 Page load time and response time are key met [...]

Can gzip Compression Really Improve Web Performance?

Last updated: February 26, 2024 The size of the web is slowly growing. Over [...]

Monitor your website’s uptime and performance

With Pingdom's website monitoring you are always the first to know when your site is in trouble, and as a result you are making the Internet faster and more reliable. Nice, huh?

START YOUR FREE 30-DAY TRIAL

MONITOR YOUR WEB APPLICATION PERFORMANCE

Gain availability and performance insights with Pingdom – a comprehensive web application performance and digital experience monitoring tool.

START YOUR FREE 30-DAY TRIAL
Start monitoring for free