How To Horizontally Scale a Laravel 4 App with a PostgreSQL Database
There are two methods to scaling an application, service, server, etc. The first, vertical scaling, calls for more resources to a machine. The second, horizontal scaling, calls for a separation of functionality to create a more piecemeal assembly of parts.
For example, does a machine spit out memory errors in the syslog? It may make sense to just add more RAM or a swapfile. However, let's say the database server is growing to a large amount of entries and the web server alone is starting to increase in traffic – a better idea may be to set up a more controllable environment (not to mention more cost effective). To do so, a separation of the web server and database server into separate machines is the key. That is horizontal scaling.
Two droplets each running Debian 7. Each VPS should have completed Initial Server Setup tutorial.
A basic understanding of Linux commands and what they do. See An Introduction to Linux Basics for a good starting point.
You will need to have installed Laravel successfully on one of the droplets. This tutorial will work for NGINX + Laravel 4 (skip the Wrap Up step): Laravel + Nginx
Do not install a database on the same virtual server as your Laravel install
For the sake of simplicity, we will refer to the first droplet with the Laravel and Nginx install as the Laravel droplet with an IP of 192.0.2.5. The second droplet with the PostgreSQL install will be called the database droplet with an IP of 192.0.2.1.
Prepping the Database
Horizontal scaling is a rather simple concept that can be come rather complex when you start thinking about more advanced topics such as database replication and load balancing. However we'll only be covering a basic separation of services: the web server frontend and the database backend. Luckily PostgreSQL and Laravel make this a rather simple process.
First we will need to install PostgreSQL on our database droplet:
sudo apt-get install postgresql
Next, we must create a database and user within the server that will have the proper permissions to interact with the database. To do so, we must log into the PostgreSQL server:
sudo -u postgres psql
First, let's create the database user:
CREATE USER databaseuser WITH PASSWORD 'password'; GRANT CREATE ON SCHEMA public TO databaseuser; GRANT USAGE ON SCHEMA public TO databaseuser;
Then create the database with the user as the owner and then quit the server:
CREATE DATABASE mydatabase WITH OWNER databaseuser; \q
Next, the database droplet will need to know that it's okay for the Laravel droplet to connect to it. PostgreSQL has a client authentication file that makes this super easy.
sudo nano /etc/postgresql/9.1/main/pg_hba.conf
Add a line that includes the connection, database name, database user, address to be accepted, and the method of connection:
# IPv4 local connections: host mydatabase databaseuser 192.0.2.5/32 md5
Save and exit, then open up postgresql.conf and find the line that says "listen_addresses = 'localhost'".
sudo nano /etc/postgresql/9.1/main/postgresql.conf
listen_addresses = '192.0.2.1'
You may also change this value to one that will accept any address:
listen_addresses = '*'
Save, exit, and restart the PostgreSQL server:
sudo service postgresql restart
The first thing that needs to be done is to give PHP some knowledge of how to work with the PostgreSQL server. Do so by installing the php5-pgsql extension.
sudo apt-get install php5-pgsql
sudo service php5-fpm restart
Next we need to tell Laravel where our database server is located and how to access it. If you followed the NGINX + Laravel tutorial, then Laravel should be installed at
sudo nano /var/www/laravel/app/config/database.php
First let's have Laravel use it's PostgreSQL driver:
'default' => 'pgsql',
Next, let's setup information about the PostgreSQL server.
'pgsql' => array( 'driver' => 'pgsql', 'host' => '192.0.2.1', 'database' => 'mydatabase', 'username' => 'databaseuser', 'password' => 'password', 'charset' => 'utf8', 'prefix' => '', 'schema' => 'public', ),
Save and exit.
Testing the Connection
To test this connection, let's run a migration in from the command line that will help build our database tables out.
Note: Migrations isn't an extra package to be installed. It comes with laravel and it's a set of commands to interact with our database.
First enter the application directory where artisan is located.
Great! Now it's time to install migrations and see if our database connection is working.
php artisan migrate:install
If this command runs successfully without errors you should see a new table in your database called migrations.
Wrapping it Up
As you can see, splitting servers is rather simple. By combining horizontal scaling with vertical scaling, a sysadmin can achieve separation of services and increased performance. Even better these methods require 0 extra software.