{"id":37962,"date":"2025-04-10T10:09:38","date_gmt":"2025-04-10T08:09:38","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=37962"},"modified":"2025-04-10T10:09:41","modified_gmt":"2025-04-10T08:09:41","slug":"postgresql-18-support-for-asynchronous-i-o","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/","title":{"rendered":"PostgreSQL 18: Support for asynchronous I\/O"},"content":{"rendered":"\n<p>This is maybe one the biggest steps forward for PostgreSQL: PostgreSQL 18 will come with support for asynchronous I\/O. Traditionally PostgreSQL relies on the operating system to hide the latency of writing to disk, which is done synchronously and can lead to double buffering (PostgreSQL shared buffers and the OS file cache). This is most important for WAL writes, as PostgreSQL must make sure that changes are flushed to disk and needs to wait until it is confirmed. <\/p>\n\n\n\n<p>Before we do some tests let&#8217;s see what&#8217;s new from a parameter perspective. One of the new parameters is <code>io_method<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# show io_method;\n io_method \n-----------\n worker\n(1 row)\n<\/pre><\/div>\n\n\n<p>The default is &#8220;worker&#8221; and the maximum number of worker processes to perform asynchronous is controller by <code>io_workers<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# show io_workers;\n io_workers \n------------\n 3\n(1 row)\n<\/pre><\/div>\n\n\n<p>This can also be seen on the operating system:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# \\! ps aux | grep &quot;io worker&quot; | grep -v grep\npostgres   29732  0.0  0.1 224792  7052 ?        Ss   Apr08   0:00 postgres: pgdev: io worker 1\npostgres   29733  0.0  0.2 224792  9884 ?        Ss   Apr08   0:00 postgres: pgdev: io worker 0\npostgres   29734  0.0  0.1 224792  7384 ?        Ss   Apr08   0:00 postgres: pgdev: io worker 2\n<\/pre><\/div>\n\n\n<p>The other possible settings for <code>io_method<\/code> are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>io_uring<\/code>: Asynchronous I\/O using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Io_uring\" target=\"_blank\" rel=\"noreferrer noopener\">io_uring<\/a><\/li>\n\n\n\n<li><code>sync<\/code>: The behavior before PostgreSQL 18, do synchronous I\/O<\/li>\n<\/ul>\n\n\n\n<p><code>io_workers<\/code> only has an effect if <code>io_method<\/code> is set to &#8220;worker&#8221;, which is the default configuration.<\/p>\n\n\n\n<p>As usual: What follows are just some basic tests. Test for your own, in your environment with your specific workload to get some meaningful numbers. Especially if you test in a public cloud, be aware that the numbers might not show you the full truth.<\/p>\n\n\n\n<p>We&#8217;ll do the tests on an AWS EC2 <a href=\"https:\/\/aws.amazon.com\/ec2\/instance-types\/t3\/\" target=\"_blank\" rel=\"noreferrer noopener\">t3.large<\/a> instance running Debian 12. The storage volume is <a href=\"https:\/\/aws.amazon.com\/ebs\/general-purpose\/\" target=\"_blank\" rel=\"noreferrer noopener\">gp3<\/a> with ext4 (default settings):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,4,8]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ grep proc \/proc\/cpuinfo \nprocessor       : 0\nprocessor       : 1\npostgres@ip-10-0-1-209:~$ free -g\n               total        used        free      shared  buff\/cache   available\nMem:               7           0           4           0           3           7\nSwap:              0           0           0\npostgres@ip-10-0-1-209:~$ mount | grep 18\n\/dev\/nvme1n1 on \/u02\/pgdata\/18 type ext4 (rw,relatime)\n<\/pre><\/div>\n\n\n<p>PostgreSQL was initialized with the default settings:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ \/u01\/app\/postgres\/product\/18\/db_0\/bin\/initdb --pgdata=\/u02\/pgdata\/18\/data\/\nThe files belonging to this database system will be owned by user &quot;postgres&quot;.\nThis user must also own the server process.\n\nThe database cluster will be initialized with locale &quot;C.UTF-8&quot;.\nThe default database encoding has accordingly been set to &quot;UTF8&quot;.\nThe default text search configuration will be set to &quot;english&quot;.\n\nData page checksums are enabled.\n\nfixing permissions on existing directory \/u02\/pgdata\/18\/data ... ok\ncreating subdirectories ... ok\nselecting dynamic shared memory implementation ... posix\nselecting default &quot;max_connections&quot; ... 100\nselecting default &quot;autovacuum_worker_slots&quot; ... 16\nselecting default &quot;shared_buffers&quot; ... 128MB\nselecting default time zone ... Etc\/UTC\ncreating configuration files ... ok\nrunning bootstrap script ... ok\nperforming post-bootstrap initialization ... ok\nsyncing data to disk ... ok\n\ninitdb: warning: enabling &quot;trust&quot; authentication for local connections\ninitdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.\n\nSuccess. You can now start the database server using:\n\n    \/u01\/app\/postgres\/product\/18\/db_0\/bin\/pg_ctl -D \/u02\/pgdata\/18\/data\/ -l logfile start\n<\/pre><\/div>\n\n\n<p>The following settings have been changed:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,2,3,4,5,6,11]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ echo &quot;shared_buffers=&#039;2GB&#039;&quot; &gt;&gt; \/u02\/pgdata\/18\/data\/postgresql.auto.conf \npostgres@ip-10-0-1-209:~$ echo &quot;checkpoint_timeout=&#039;20min&#039;&quot; &gt;&gt; \/u02\/pgdata\/18\/data\/postgresql.auto.conf \npostgres@ip-10-0-1-209:~$ echo &quot;random_page_cost=1.1&quot; &gt;&gt; \/u02\/pgdata\/18\/data\/postgresql.auto.conf\npostgres@ip-10-0-1-209:~$ echo &quot;max_wal_size=&#039;8GB&#039;&quot; &gt;&gt; \/u02\/pgdata\/18\/data\/postgresql.auto.conf  \npostgres@ip-10-0-1-209:~$ \/u01\/app\/postgres\/product\/18\/db_0\/bin\/pg_ctl --pgdata=\/u02\/pgdata\/18\/data\/ -l \/dev\/null start\npostgres@ip-10-0-1-209:~$ \/u01\/app\/postgres\/product\/18\/db_0\/bin\/psql -c &quot;select version()&quot;\n                                        version                                        \n---------------------------------------------------------------------------------------\n PostgreSQL 18devel dbi services build on x86_64-linux, compiled by gcc-12.2.0, 64-bit\n(1 row)\npostgres@ip-10-0-1-209:~$ export PATH=\/u01\/app\/postgres\/product\/18\/db_0\/bin\/:$PATH\n<\/pre><\/div>\n\n\n<p>The first test is data loading. How long does that take when io_method is set to worker (3 times in a row), this gives a data set of around 1536MB:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,11,12,18,19,25]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\nNOTICE:  table &quot;pgbench_accounts&quot; does not exist, skipping\nNOTICE:  table &quot;pgbench_branches&quot; does not exist, skipping\nNOTICE:  table &quot;pgbench_history&quot; does not exist, skipping\nNOTICE:  table &quot;pgbench_tellers&quot; does not exist, skipping\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 31.85 s (drop tables 0.00 s, create tables 0.01 s, client-side generate 24.82 s, vacuum 0.35 s, primary keys 6.68 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 31.97 s (drop tables 0.24 s, create tables 0.00 s, client-side generate 25.44 s, vacuum 0.34 s, primary keys 5.93 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 30.72 s (drop tables 0.26 s, create tables 0.00 s, client-side generate 23.93 s, vacuum 0.55 s, primary keys 5.98 s).\n<\/pre><\/div>\n\n\n<p>The same test with &#8220;sync&#8221;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,3,4,9,15,16,22,23,29]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ psql -c &quot;alter system set io_method=&#039;sync&#039;&quot;\nALTER SYSTEM\npostgres@ip-10-0-1-209:~$ pg_ctl --pgdata=\/u02\/pgdata\/18\/data\/ restart -l \/dev\/null\npostgres@ip-10-0-1-209:~$ psql -c &quot;show io_method&quot;\n io_method \n-----------\n sync\n(1 row)\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 20.89 s (drop tables 0.29 s, create tables 0.01 s, client-side generate 14.70 s, vacuum 0.45 s, primary keys 5.44 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 21.57 s (drop tables 0.20 s, create tables 0.00 s, client-side generate 16.13 s, vacuum 0.46 s, primary keys 4.77 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 21.44 s (drop tables 0.20 s, create tables 0.00 s, client-side generate 16.04 s, vacuum 0.52 s, primary keys 4.67 s).\n<\/pre><\/div>\n\n\n<p>&#8230; and finally &#8220;io_uring&#8221;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,3,8,14,20,21,27,28,34]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ psql -c &quot;alter system set io_method=&#039;io_uring&#039;&quot;\nALTER SYSTEM\npostgres@ip-10-0-1-209:~$ pg_ctl --pgdata=\/u02\/pgdata\/18\/data\/ restart -l \/dev\/null\nwaiting for server to shut down.... done\nserver stopped\nwaiting for server to start.... done\nserver started\npostgres@ip-10-0-1-209:~$ psql -c &quot;show io_method&quot;\n io_method \n-----------\n io_uring\n(1 row)\n\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 20.63 s (drop tables 0.35 s, create tables 0.01 s, client-side generate 14.92 s, vacuum 0.47 s, primary keys 4.88 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 20.81 s (drop tables 0.29 s, create tables 0.00 s, client-side generate 14.43 s, vacuum 0.46 s, primary keys 5.63 s).\npostgres@ip-10-0-1-209:~$ pgbench -i -s 100\ndropping old tables...\ncreating tables...\ngenerating data (client-side)...\nvacuuming...                                                                                   \ncreating primary keys...\ndone in 21.11 s (drop tables 0.24 s, create tables 0.00 s, client-side generate 15.63 s, vacuum 0.53 s, primary keys 4.70 s).\n<\/pre><\/div>\n\n\n<p>There not much difference for &#8220;sync&#8221; and &#8220;io_uring&#8221;, but &#8220;worker&#8221; clearly is slower for that type of workload.<\/p>\n\n\n\n<p>Moving on, let&#8217;s see how that looks like for a standard pgbench benchmark. We&#8217;ll start with &#8220;io_uring&#8221; as this is the current setting:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,15,16,30,31,45]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 567989\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.113 ms\ninitial connection time = 8.996 ms\ntps = 946.659673 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 557640\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.152 ms\ninitial connection time = 6.994 ms\ntps = 929.408406 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 563613\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.129 ms\ninitial connection time = 16.351 ms\ntps = 939.378627 (without initial connection time)\n<\/pre><\/div>\n\n\n<p>Same test with &#8220;worker&#8221;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [1,3,8,22,23,37,38,52]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ psql -c &quot;alter system set io_method=&#039;worker&#039;&quot;\nALTER SYSTEM\npostgres@ip-10-0-1-209:~$ pg_ctl --pgdata=\/u02\/pgdata\/18\/data\/ restart -l \/dev\/null\nwaiting for server to shut down............. done\nserver stopped\nwaiting for server to start.... done\nserver started\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &amp;lt;builtin: TPC-B (sort of)&amp;gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 549176\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.185 ms\ninitial connection time = 7.189 ms\ntps = 915.301403 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &amp;lt;builtin: TPC-B (sort of)&amp;gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 564898\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.124 ms\ninitial connection time = 11.332 ms\ntps = 941.511304 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &amp;lt;builtin: TPC-B (sort of)&amp;gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 563041\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.131 ms\ninitial connection time = 9.120 ms\ntps = 938.412979 (without initial connection time)\n<\/pre><\/div>\n\n\n<p>&#8230; and finally &#8220;sync&#8221;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1,3,8,22,23,37,38,52]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ psql -c &quot;alter system set io_method=&#039;sync&#039;&quot;\nALTER SYSTEM\npostgres@ip-10-0-1-209:~$ pg_ctl --pgdata=\/u02\/pgdata\/18\/data\/ restart -l \/dev\/null\nwaiting for server to shut down............ done\nserver stopped\nwaiting for server to start.... done\nserver started\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 560420\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.141 ms\ninitial connection time = 12.000 ms\ntps = 934.050237 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 560077\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.143 ms\ninitial connection time = 7.204 ms\ntps = 933.469665 (without initial connection time)\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=2 --jobs=2\npgbench (18devel dbi services build)\nstarting vacuum...end.\ntransaction type: &lt;builtin: TPC-B (sort of)&gt;\nscaling factor: 100\nquery mode: simple\nnumber of clients: 2\nnumber of threads: 2\nmaximum number of tries: 1\nduration: 600 s\nnumber of transactions actually processed: 566150\nnumber of failed transactions: 0 (0.000%)\nlatency average = 2.120 ms\ninitial connection time = 7.579 ms\ntps = 943.591451 (without initial connection time)\n<\/pre><\/div>\n\n\n<p>As you see there is not much difference, no matter the io_method. Let&#8217;s stress the system a bit more (only putting the summaries here):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=10 --jobs=10\n## sync\ntps = 2552.785398 (without initial connection time)\ntps = 2505.476064 (without initial connection time)\ntps = 2542.419230 (without initial connection time)\n## io_uring\ntps = 2511.138931 (without initial connection time)\ntps = 2529.705311 (without initial connection time)\ntps = 2573.195751 (without initial connection time)\n## worker\ntps = 2531.657962 (without initial connection time)\ntps = 2523.854335 (without initial connection time)\ntps = 2515.490351 (without initial connection time)\n<\/pre><\/div>\n\n\n<p>Some picture, there is not much difference. One last test, hammering the system even more:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres@ip-10-0-1-209:~$ pgbench --time=600 --client=20 --jobs=20\n## worker\ntps = 2930.268033 (without initial connection time)\ntps = 2799.499964 (without initial connection time)\ntps = 3033.491153 (without initial connection time)\n## io_uring\ntps = 2942.542882 (without initial connection time)\ntps = 3061.487286 (without initial connection time)\ntps = 2995.175169 (without initial connection time)\n## sync\ntps = 2997.654084 (without initial connection time)\ntps = 2924.269626 (without initial connection time)\ntps = 2753.853272 (without initial connection time)\n<\/pre><\/div>\n\n\n<p>At least for these tests, there is not much difference between the three settings for io_method (sync seems to be a bit slower), but I think this is still great. For such a massive change getting to the same performance as before is great. Things in PostgreSQL improve all the time, and I am sure there will be a lot of improvements in this area as well.<\/p>\n\n\n\n<p>Usually I link to the commit here, but in this case that would be a whole bunch of commits. To everyone involved in this, a big thank you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is maybe one the biggest steps forward for PostgreSQL: PostgreSQL 18 will come with support for asynchronous I\/O. Traditionally PostgreSQL relies on the operating system to hide the latency of writing to disk, which is done synchronously and can lead to double buffering (PostgreSQL shared buffers and the OS file cache). This is most [&hellip;]<\/p>\n","protected":false},"author":29,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229,198],"tags":[77],"type_dbi":[],"class_list":["post-37962","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","category-database-management","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>PostgreSQL 18: Support for asynchronous I\/O - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PostgreSQL 18: Support for asynchronous I\/O\" \/>\n<meta property=\"og:description\" content=\"This is maybe one the biggest steps forward for PostgreSQL: PostgreSQL 18 will come with support for asynchronous I\/O. Traditionally PostgreSQL relies on the operating system to hide the latency of writing to disk, which is done synchronously and can lead to double buffering (PostgreSQL shared buffers and the OS file cache). This is most [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2025-04-10T08:09:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-10T08:09:41+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Westermann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@westermanndanie\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Westermann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\"},\"author\":{\"name\":\"Daniel Westermann\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"headline\":\"PostgreSQL 18: Support for asynchronous I\/O\",\"datePublished\":\"2025-04-10T08:09:38+00:00\",\"dateModified\":\"2025-04-10T08:09:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\"},\"wordCount\":474,\"commentCount\":0,\"keywords\":[\"PostgreSQL\"],\"articleSection\":[\"Database Administration &amp; Monitoring\",\"Database management\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\",\"name\":\"PostgreSQL 18: Support for asynchronous I\/O - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2025-04-10T08:09:38+00:00\",\"dateModified\":\"2025-04-10T08:09:41+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PostgreSQL 18: Support for asynchronous I\/O\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\",\"name\":\"Daniel Westermann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"caption\":\"Daniel Westermann\"},\"description\":\"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.\",\"sameAs\":[\"https:\/\/x.com\/westermanndanie\"],\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"PostgreSQL 18: Support for asynchronous I\/O - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/","og_locale":"en_US","og_type":"article","og_title":"PostgreSQL 18: Support for asynchronous I\/O","og_description":"This is maybe one the biggest steps forward for PostgreSQL: PostgreSQL 18 will come with support for asynchronous I\/O. Traditionally PostgreSQL relies on the operating system to hide the latency of writing to disk, which is done synchronously and can lead to double buffering (PostgreSQL shared buffers and the OS file cache). This is most [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/","og_site_name":"dbi Blog","article_published_time":"2025-04-10T08:09:38+00:00","article_modified_time":"2025-04-10T08:09:41+00:00","author":"Daniel Westermann","twitter_card":"summary_large_image","twitter_creator":"@westermanndanie","twitter_misc":{"Written by":"Daniel Westermann","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/"},"author":{"name":"Daniel Westermann","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"headline":"PostgreSQL 18: Support for asynchronous I\/O","datePublished":"2025-04-10T08:09:38+00:00","dateModified":"2025-04-10T08:09:41+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/"},"wordCount":474,"commentCount":0,"keywords":["PostgreSQL"],"articleSection":["Database Administration &amp; Monitoring","Database management"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/","url":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/","name":"PostgreSQL 18: Support for asynchronous I\/O - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2025-04-10T08:09:38+00:00","dateModified":"2025-04-10T08:09:41+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-18-support-for-asynchronous-i-o\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"PostgreSQL 18: Support for asynchronous I\/O"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66","name":"Daniel Westermann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","caption":"Daniel Westermann"},"description":"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.","sameAs":["https:\/\/x.com\/westermanndanie"],"url":"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/37962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=37962"}],"version-history":[{"count":20,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/37962\/revisions"}],"predecessor-version":[{"id":37983,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/37962\/revisions\/37983"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=37962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=37962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=37962"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=37962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}