Getting Started with PostgreSQL Streaming Replication
Tags: postgres, database, sql, highavailability
Published: 2018-09-13 15:46:43

---
title: Getting Started with PostgreSQL Streaming Replication
published: true
description: How to set up Streaming Replication in PostgreSQL for high availability PostgreSQL hosting. 1. Configuration on Master Node. 2. Configuration on Standby Nodes
tags: Postgres, Database, SQL, High Availability,
canonical_url: https://scalegrid.io/blog/getting-started-with-postgresql-streaming-replication/
---
<link rel="canonical" href="https://scalegrid.io/blog/getting-started-with-postgresql-streaming-replication/" />

<a href="https://scalegrid.io/blog/getting-started-with-postgresql-streaming-replication/"><img src="https://thepracticaldev.s3.amazonaws.com/i/ehmklnq7a43jh0f0ro17.png" alt="PostgreSQL Streaming Replication for High Availability - ScaleGrid Blog" ></a>
<p style="text-align: justify;">In this blog post, we dive into the nuts and bolts of setting up Streaming Replication (SR) in PostgreSQL. Streaming replication is the fundamental building block for achieving high availability in your <a href="https://scalegrid.io/postgresql.html" target="_blank">PostgreSQL hosting</a>, and is produced by running a master-slave configuration.</p>

<p style="text-align: justify;">Read the original article: <a href="https://scalegrid.io/blog/getting-started-with-postgresql-streaming-replication/" target="_blank">Getting Started with PostgreSQL Streaming Replication</a>

<h1 style="padding:10px 0px;">Master-Slave Terminology</h1>
<h3>Master/Primary Server</h3>
<ul>
	<li>The server that can take writes.</li>
	<li>Also called read/write server.</li>
</ul>
<h3>Slave/Standby Server</h3>
<ul>
	<li>A server where the data is kept in sync with the master continuously.</li>
	<li>Also called backup server or replica.</li>
	<li>A warm standby server is one that cannot be connected to until it is promoted to become a master server.</li>
	<li>In contrast, a <a href="https://www.postgresql.org/docs/10/static/hot-standby.html" target="_blank">hot standby server</a> can accept connections and serves read-only queries. For the rest of this discussion, we will be focusing only on hot standby servers.</li>
</ul>

<p style="text-align: justify;">Data is written to the master server and propagated to the slave servers. In case there are an issue with the existing master server, one of the slave servers will take over and continue to take writes ensuring availability of the system.</p>

<h1 style="padding:10px 0px;">WAL Shipping-Based Replication</h1>
<h2>What is WAL?</h2>
<ul>
	<li>WAL stands for <a href="https://www.postgresql.org/docs/9.1/static/wal-intro.html" target="_blank">Write-Ahead Logging</a>.</li>
	<li>It is a log file where all the modifications to the database are written before they're applied/written to data files.</li>
	<li>WAL is used for recovery after a database crash, ensuring data integrity.</li>
	<li>WAL is used in database systems to achieve atomicity and durability.</li>
</ul>

<h2>How is WAL Used For Replication?</h2>
<p style="text-align: justify;">Write-ahead log records are used to keep the data in sync between the database servers. This is achieved in two ways:</p>

<h3>File-Based Log Shipping</h3>
<ul>
	<li>WAL log files are shipped from the master to the standby servers to keep data in sync.</li>
	<li>Master can directly copy the logs to standby server storage or can share storage with the standby servers.</li>
	<li>One WAL log file can contain up to 16MB of data.</li>
	<li>The WAL file is shipped only after it reaches that threshold.</li>
	<li><em>This will cause a delay in replication and also increase chances of losing data if the master crashes and logs are not archived</em></li>
</ul>
<h3>Streaming WAL Records</h3>
<ul>
	<li>WAL record chunks are streamed by database servers to keep data in sync.</li>
	<li>The standby server connects to the master to receive the WAL chunks.</li>
	<li>The WAL records are streamed as they are generated.</li>
	<li>The streaming of WAL records need not wait for the WAL file to be filled.</li>
	<li><em>This allows a standby server to stay more up-to-date than is possible with file-based log shipping.</em></li>
	<li>By default, streaming replication is asynchronous even though it also supports synchronous replication.</li>
</ul>

<p style="text-align: justify;">Both the methods have their pros and cons. Using file-based shipping enables point-in-time recovery and continuous archiving, while streaming ensures the immediate data availability on the standby servers. However, you can configure PostgreSQL to use both methods at the same time and enjoy the benefits. In this blog, we concentrate mainly on streaming replication to achieve PostgreSQL high availability.</p>


<h1 style="padding:10px 0px;">How To Set Up Streaming Replication?</h1>
<a href="https://scalegrid.io/blog/wp-content/uploads/2018/09/postgres_streaming.jpg"><img class="size-full wp-image-3412" src="https://scalegrid.io/blog/wp-content/uploads/2018/09/postgres_streaming.jpg" alt="PostgreSQL Streaming Replication" width="836" height="554" /></a>
<p style="text-align: justify;">Setting up streaming replication in PostgreSQL is very simple. Assuming PostgreSQL is already installed on all the servers, you can follow these steps to get started:</p>

<h2>Configuration on Master Node</h2>
<ul>
	<li>Initialize the database on the master node using initdb utility.</li>
	<li>Create a role/user with replication privileges by running the below command. Post running the command, you can verify it by running \du to list them on psql.
<ul>
	<li>  CREATE USER &lt;user_name&gt; REPLICATION LOGIN ENCRYPTED PASSWORD ’&lt;password&gt;’;</li>
</ul>
</li>
	<li>Configure properties related to streaming replication in the master PostgreSQL configuration (postgresql.conf) file:
<table class="table table-bordered" style="margin-top:20px;">
<tbody>
<tr>
<td># Possible values are <em>replica|minimal|logical</em><br>
<strong>wal_level</strong> = replica<br>
# required for pg_rewind capability when standby goes out of sync with master<br>
<strong>wal_log_hints</strong> = on<br>
# sets the maximum number of concurrent connections from the standby servers.<br>
<strong>max_wal_senders</strong> = 3<br>
# The below parameter is used to tell the master to keep the minimum number of<br>
# segments of WAL logs so that they are not deleted before standby consumes them.<br>
# each segment is 16MB<br>
<strong>wal_keep_segments</strong> = 8<br>
# The below parameter enables read only connection on the node when it is in<br>
# standby role. This is ignored when the server is running as master.<br>
<strong>hot_standby</strong> = on</td><br>
</tr>
</tbody>
</table>
</li>
<li>Add replication entry in pg_hba.conf file to allow replication connections between the servers:
<table class="table table-bordered" style="margin-top:20px;">
<tbody>
<tr>
<td># Allow replication connections from localhost,<br>
# by a user with the replication privilege.<br>
# TYPE    DATABASE    USER    ADDRESS    METHOD<br>
host    replication    repl_user    IPaddress(CIDR)    md5</td>
</tr>
</tbody>
</table>
</li>
<li>Restart the PostgreSQL service on the master node for the changes to take effect.</li>
</ul>

<h2>Configuration on Standby Node(s)</h2>
<ul>
	<li>Create the base backup of master node using pg_basebackup utility and use it as a starting point for the standby.
<table class="table table-bordered" style="margin-top:20px;">
<tbody>
<tr>
<td># Explaining a few options used for pg_basebackup utility<br>
# -X option is used to include the required transaction log files (WAL files) in the<br>
# backup. When you specify stream, this will open a second connection to the server<br>
# and start streaming the transaction log at the same time as running the backup.<br>
# -c is the checkpoint option. Setting it to fast will force the checkpoint to be
# created soon.<br>
# -W forces pg_basebackup to prompt for a password before connecting<br>
# to a database.<br>
<em><strong>pg_basebackup</strong> -D &lt;data_directory&gt;  -h &lt;master_host&gt; -X stream -c fast -U repl_user -W</em></td>
</tr>
</tbody>
</table>
</li>
<li>Create the replication configuration file if not present (it is created automatically if -R option is provided in pg_basebackup):
<table class="table table-bordered" style="margin-top:20px;">
<tbody>
<tr>
<td># Specifies whether to start the server as a standby. In streaming replication,<br>
# this parameter must be set to on.<br>
<strong>standby_mode</strong> = 'on'<br>
# Specifies a connection string which is used for the standby server to connect<br>
# with the primary/master.<br>
<strong>primary_conninfo</strong>  = 'host=&lt;master_host&gt; port=&lt;postgres_port&gt; user=&lt;replication_user&gt; password=&lt;password&gt; application_name=”host_name”'<br>
# Specifies recovering to a particular timeline. The default is to recover along the<br>
# same timeline that was current when the base backup was taken.<br>
# Setting this to latest recovers to the latest timeline found<br>
# in the archive, which is useful in a standby server.<br>
<strong>recovery_target_timeline</strong> = ‘latest’</td>
</tr>
</tbody>
</table>
</li>
<li>Start the standby.</li>
</ul>

<p style="text-align: justify;">The standby configuration has to be done on all the standby servers. Once the configuration is done and a standby is started, it will connect to master and start streaming logs. This will setup the replication and can be verified by running the SQL statement "<strong>SELECT * FROM pg_stat_replication;</strong><em>".</em></p>

<p style="text-align: justify;">By default, streaming replication is asynchronous. If you wish to make it synchronous, then you can configure it using the following parameters:</p>

<table class="table table-bordered" style="margin-top:20px;">
<tbody>
<tr>
<td># num_sync is the number of synchronous standbys from which transactions<br>
# need to wait for replies.<br>
# standby_name is same as application_name value in recovery.conf<br>
# If all standby servers have to be considered for synchronous then set value ‘*’<br>
# If only specific standby servers needs to be considered, then specify them as
# comma-separated list of standby_name.<br>
# The name of a standby server for this purpose is the application_name setting of the<br>
# standby, as set in the primary_conninfo of the<br>
# standby's WAL receiver.<br>
<strong>synchronous_standby_names</strong> = ‘num_sync ( standby_name [, ...] )’</td>
</tr>
</tbody>
</table>

<p style="text-align: justify;"><strong>Synchronous_commit</strong> must be set to on for synchronous replication and this is the default. PostgreSQL provides very flexible options for synchronous commit and can be configured at user/database levels. Valid values are as follows:</p>

<ul>
	<li><strong>Off</strong> - Transaction commit is acknowledged to the client even before that transaction record is actually flushed to WAL log file on that node.</li>
	<li><strong>Local</strong> -  Transaction commit is acknowledged to the client only after that transaction record is flushed into the WAL log file on that node.</li>
	<li><strong>Remote_write</strong> - Transaction commit is acknowledged to the client only after the server(s) specified by synchronous_standby_names confirms that the transaction record was written to the disk cache, but not necessarily after being flushed to the WAL log file.</li>
	<li><strong>On</strong> - Transaction commit is acknowledged to the client only after the server(s) specified by synchronous_standby_names confirms that the transaction record is flushed to the WAL log file.</li>
	<li><strong>Remote_apply</strong> - Transaction commit is acknowledged to the client only after the server(s) specified by synchronous_standby_names confirms that the transaction record is flushed to the WAL log file and it is applied to the database.</li>
</ul>

<p style="text-align: justify;">Setting synchronous_commit to off or local in synchronous replication mode will make it work like asynchronous, and can help you achieve better write performance. However, this will have higher risk of data loss and read delays on standby servers. If set to remote_apply, it will ensure immediate data availability at standby servers, but write performance may degrade since it should be applied on all/mentioned standby servers.</p>

<p style="text-align: justify;">You can enable the archive mode if you're planning to use continuous archiving and point-in-time recovery. While it's not mandatory for streaming replication, enabling archive mode has extra benefits. If archive mode is not on, then we need to use the <strong>replication slots</strong> feature or ensure that <strong>wal_keep_segments</strong> value is set high enough based on load.</p>

<p style="text-align: justify; padding-bottom:20px;">Refer to this <a title="Modern PostgreSQL High Availability" href="https://pgconf.ru/media/2018/02/19/Alvaro_Modern%20PostgreSQL%20High%20Availability.pdf" target="_blank">excellent presentation</a> to go into more details of high availability in PostgreSQL. In our next blog post, we'll introduce you to the world of tools used to manage high availability for PostgreSQL using streaming replication.</p>