{"id":3753,"date":"2022-12-24T01:01:00","date_gmt":"2022-12-24T01:01:00","guid":{"rendered":"https:\/\/www.javaadvent.com\/?p=3753"},"modified":"2022-12-17T22:46:47","modified_gmt":"2022-12-17T22:46:47","slug":"using-postgres-as-a-message-queue","status":"publish","type":"post","link":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html","title":{"rendered":"Using Postgres as a Message Queue"},"content":{"rendered":"\n<p>Databases <a href=\"https:\/\/mikehadlow.blogspot.com\/2012\/04\/database-as-queue-anti-pattern.html\">are no message queues<\/a> is a well-established claim that has been discussed in many blog postings and conference presentations. But with advancements in relational databases, does this claim still stand up to scrutiny? Looking at modern versions of Postgres, the answer is often no. Therefore, this article looks into Postgres\u2019 lightweight notification mechanism and discusses how it can be leveraged to implement a simple, but effective push-based message queue. It also looks into using this queue for communicating among replicas on a Kubernetes deployment, and into implementing a generic task processing framework.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Postgres as a message queue<\/h2>\n\n\n\n<p>Postgres is, of course, a relational database that implements a large fraction of the SQL standard. But beyond that, Postgres implements many other, non-standardized features that can also be executed via its extension upon SQL. One such feature is the <em><a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-listen.html\">LISTEN<\/a><\/em> and <em><a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-notify.html\">NOTIFY<\/a><\/em> mechanism which allows for sending asynchronous messages across database connections. And of course these commands can be issued via JDBC. For a simple hello-world example, consider a JVM to listen on a given <code>hello_world_channel<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\ntry (Connection conn = getConnection()) {\n\n\u00a0 try (Statement stmt = conn.createStatement()) {\n\u00a0\u00a0\u00a0 stmt.execute(\u201cLISTEN hello_world_channel&quot;);\n\u00a0 }\n\n\u00a0 PGNotification&#x5B;] notifications =\u00a0 conn\n    .unwrap(PgConnection.class)\n    .getNotifications(0);\n\n  System.out.println(\n    &quot;Hello &quot; + notifications&#x5B;0].getParameter() + &quot;!&quot;);\n}\n<\/pre><\/div>\n\n\n<p>To receive notifications, one needs to specify the name of a channel to <code>LISTEN<\/code> to. The name of the channel can be chosen arbitrarily. To receive notifications, one needs to unwrap the connection to the Postgres JDBC driver\u2019s <code>PgConnection<\/code>. From there, received notifications can be read with a timeout, or 0 if one wants to wait indefinitely. A second JVM can now send a notification using a similarly simple setup:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\ntry (\n    Connection conn = getConnection(); \n    Statement stmt = conn.createStatement()) {\n  stmt.execute(&quot;NOTIFY hello_world_channel, \u2018World\u2019&quot;);\n}\n<\/pre><\/div>\n\n\n<p>which will cause the first JVM to print <code>Hello World!<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Defining triggers to create a simple message queue<\/h2>\n\n\n\n<p>Often, a notification is not sent directly, but via a trigger on a table. For example, to implement the mentioned message queue, one could start basis in a simple table as:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE TABLE MY_MESSAGES (\n  RECEIVER VARCHAR(200),\n  ID SERIAL,\n  PAYLOAD JSON,\n  PROCESSED BOOLEAN);\n<\/pre><\/div>\n\n\n<p>To fire a notification whenever a message is inserted into the table, a function such as the following implements this in Postgres\u2019 procedural language pgSQL without altering the inserted row:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE FUNCTION MY_MESSAGES_FCT()\nRETURNS TRIGGER AS\n$BODY$\nBEGIN\n\u00a0 PERFORM pg_notify(\u2018my_message_queue\u2019, NEW.RECEIVER);\n\u00a0 RETURN NEW;\nEND;\n$BODY$\nLANGUAGE PLPGSQL;\n<\/pre><\/div>\n\n\n<p>In the above function, the pg_notify function is invoked, which simply triggers a <em>NOTIFY<\/em> with the second argument as a payload but avoids possible SQL injection which could occur with string concatenation. This function can now be installed as a trigger on any insertions in <em>MY_MESSAGES<\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nCREATE TRIGGER MY_MESSAGES_TRG\nAFTER INSERT ON MY_MESSAGES\nFOR EACH ROW\nEXECUTE PROCEDURE MY_MESSAGES_FCT();\n<\/pre><\/div>\n\n\n<p>This way, one or several listeners can be notified on the arrival of new messages, for example as replicas within a Kubernetes deployment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Postgres notifications and connection pooling<\/h2>\n\n\n\n<p>One caveat with Postgres\u2019 notification mechanism is that it typically requires the creation of a dedicated Connection for receiving notifications. This is due to the connection being used for sending notifications back via the channel that the JDBC client established when opening a connection and executing the <code>LISTEN<\/code> statement. This requires that the connection is long-lived, which does not normally play well with pooled DataSources. Instead, one should create a dedicated Connection via the DriverManager API.<\/p>\n\n\n\n<p>Note that this also occupies a full connection on the Postgres server where connections typically are pooled, as well. For this reason, a Postgres server might start rejecting new connection attempts if too many JVMs already occupy a dedicated connection for listening for notifications. It might therefore become necessary to increase the maximum number of allowed concurrent connections in the Postgres server instance. As connections for receiving notifications do often run idle and require few machine resources, this is not normally a consequential change. Quite the opposite, if the listening for notifications can substitute frequent polling against the database, this approach might even free resources.<\/p>\n\n\n\n<p>With this downside, the approach of Postgres does also bring a less obvious upside. With Oracle, for example, the database does not require a dedicated connection. However, this requires that the database can actively call the notified application on a given host and port. This might not always be possible, for example on Kubernetes when multiple replicas share a common host.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using Spring integration\u2019s JDBC message queue on Postgres<\/h2>\n\n\n\n<p>This functionality will be available in <a href=\"https:\/\/docs.spring.io\/spring-integration\/docs\/6.0.0-RC2\/reference\/html\/\">Spring integration with imminent arrival of version six<\/a>. Spring integration does already offer a JDBC-based queue implementation. But as of today, it only offers polling messages, or to receive push messages when operating on the same queue object within a single JVM. By defining a trigger, similarly to the one above, as suggested in Spring integration\u2019s <a href=\"https:\/\/github.com\/spring-projects\/spring-integration\/blob\/main\/spring-integration-jdbc\/src\/main\/resources\/org\/springframework\/integration\/jdbc\/schema-postgresql.sql\">schema-postgres.sql file<\/a>, Spring integration allows for receiving messages that are sent via a regular <code>JdbcChannelMessageStore<\/code>.<\/p>\n\n\n\n<p>The message allows to send a message with any serializable payload to a given channel as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nJdbcChannelMessageStore messageStore = \n  new JdbcChannelMessageStore(getDataSource());\nmessageStore.setChannelMessageStoreQueryProvider(\n  new PostgresChannelMessageStoreQueryProvider());\n\nmessageStore.addMessageToGroup(\n  \u201csome-channel\u201d, \n  new GenericMessage&lt;&gt;(\u201cWorld\u201d);\n<\/pre><\/div>\n\n\n<p>which Spring integration 6 now allows to receive via push notification from any other connected JVM via:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nPostgresChannelMessageTableSubscriber subscriber = \n  new PostgresChannelMessageTableSubscriber(() -&gt; \n    DriverManager.getConnection(\n      getJdbcUrl(), \n      getUsername(), \n      getPassword()).unwrap(PgConnection.class);\nsubscriber.start()\n\nPostgresSubscribableChannel channel = \n  new PostgresSubscribableChannel(\n    messageStore, \n    &quot;some-channel&quot;,\n     subscriber);\nchannel.subscribe(message -&gt; System.out.println(\n  \u201cHello \u201c + message.getPayload() + \u201c!\u201d);\n<\/pre><\/div>\n\n\n<p>Before, inter-JVM communication like this was previously only possible by polling the channel for new messages while the above mechanism allows for quasi-instant communication among different VMs. When creating a multi-node application that already uses Postgres, this can be used as an easy way to communicate between VMs. For example, one could use Spring integration\u2019s <code>LockRegistryLeaderInitiator<\/code> to determine a node that executes unshared work. If multiple nodes can receive an HTTP message that is meant for this leader node to process, those nodes can now forward this call via a JDBC message store which notifies the leader instantaneously. This can be achieved with only a few lines of code and without a need to expand the technical stack to additional technology such as Zookeeper.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing a generic task processor with push notifications to workers<\/h2>\n\n\n\n<p>For a real-world example of inter-JVM communication using Postgres, the Norwegian tax authority <a href=\"https:\/\/github.com\/Skatteetaten\/skatteprosessen-task\">offers a thin library for generic task processing<\/a> using the database\u2019s notification API. If a batch of new tasks is created, multiple worker nodes are notified of the additional work and wake up to poll for new messages. This work will continue until no additional tasks are available when the workers will get back to sleep.<\/p>\n\n\n\n<p>This shows another strength of the notification mechanism where it allows any amount of listeners to a given channel to be notified simultaneously and without preallocating table rows to a given node. Thanks to Postgres\u2019 multiversion concurrency control, this allocation can be decided upon selecting from a database where each node can acquire row locks to determine its tasks from a table, without the need for a separate allocation implementation within a possible alternative notification framework. All this makes Postgres a good choice for using the database as a queue, especially if Postgres already is part of the technological stack.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article looks into Postgres\u2019 lightweight notification mechanism &#038; discusses how it can be leveraged to implement a simple, but effective push-based message queue.<\/p>\n","protected":false},"author":98,"featured_media":3227,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[646],"tags":[616,322,668],"coauthors":[483],"class_list":["post-3753","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jvm-advent-2022","tag-kubernetes","tag-postgresql","tag-queue"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Using Postgres as a Message Queue - JVM Advent<\/title>\n<meta name=\"description\" content=\"This article looks into Postgres\u2019 lightweight notification mechanism &amp; discusses how it can be leveraged to implement a simple, but effective push-based message queue.\" \/>\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.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Postgres as a Message Queue - JVM Advent\" \/>\n<meta property=\"og:description\" content=\"This article looks into Postgres\u2019 lightweight notification mechanism &amp; discusses how it can be leveraged to implement a simple, but effective push-based message queue.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html\" \/>\n<meta property=\"og:site_name\" content=\"JVM Advent\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/\" \/>\n<meta property=\"article:published_time\" content=\"2022-12-24T01:01:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Rafael Winterhalter\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/rafaelcodes\" \/>\n<meta name=\"twitter:site\" content=\"@javaadvent\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Rafael Winterhalter\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html\"},\"author\":{\"name\":\"Rafael Winterhalter\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/e2a44b138b60fcdd955d0cbd27a9d265\"},\"headline\":\"Using Postgres as a Message Queue\",\"datePublished\":\"2022-12-24T01:01:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html\"},\"wordCount\":1066,\"commentCount\":6,\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1\",\"keywords\":[\"kubernetes\",\"PostgreSQL\",\"Queue\"],\"articleSection\":[\"2022\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html\",\"name\":\"Using Postgres as a Message Queue - JVM Advent\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1\",\"datePublished\":\"2022-12-24T01:01:00+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/e2a44b138b60fcdd955d0cbd27a9d265\"},\"description\":\"This article looks into Postgres\u2019 lightweight notification mechanism & discusses how it can be leveraged to implement a simple, but effective push-based message queue.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2021\\\/12\\\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1\",\"width\":800,\"height\":800},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2022\\\/12\\\/using-postgres-as-a-message-queue.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javaadvent.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Postgres as a Message Queue\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/\",\"name\":\"JVM Advent\",\"description\":\"The JVM Programming Advent Calendar\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javaadvent.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/e2a44b138b60fcdd955d0cbd27a9d265\",\"name\":\"Rafael Winterhalter\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g25a2acc71e33aff93eefa5348c37d572\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g\",\"caption\":\"Rafael Winterhalter\"},\"description\":\"Rafael works as a software consultant in Oslo, Norway. He is a proponent of static typing and a JVM enthusiast with particular interest in code instrumentation, concurrency and functional programming. Rafael blogs about software development, regularly presents at conferences and was pronounced a JavaOne Rock Star. When coding outside of his work place, he contributes to a wide range of open source projects and often works on Byte Buddy, a library for simple runtime code generation for the Java virtual machine. For his work, Rafael received a Duke's Choice award, an Oracle groundbreaker award and was elected a Java Champion.\",\"sameAs\":[\"http:\\\/\\\/rafael.codes\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/rafaelcodes\"],\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/author\\\/rafael-wth\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Postgres as a Message Queue - JVM Advent","description":"This article looks into Postgres\u2019 lightweight notification mechanism & discusses how it can be leveraged to implement a simple, but effective push-based message queue.","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.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html","og_locale":"en_US","og_type":"article","og_title":"Using Postgres as a Message Queue - JVM Advent","og_description":"This article looks into Postgres\u2019 lightweight notification mechanism & discusses how it can be leveraged to implement a simple, but effective push-based message queue.","og_url":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html","og_site_name":"JVM Advent","article_publisher":"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/","article_published_time":"2022-12-24T01:01:00+00:00","og_image":[{"width":800,"height":800,"url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","type":"image\/png"}],"author":"Rafael Winterhalter","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/rafaelcodes","twitter_site":"@javaadvent","twitter_misc":{"Written by":"Rafael Winterhalter","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#article","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html"},"author":{"name":"Rafael Winterhalter","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/e2a44b138b60fcdd955d0cbd27a9d265"},"headline":"Using Postgres as a Message Queue","datePublished":"2022-12-24T01:01:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html"},"wordCount":1066,"commentCount":6,"image":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","keywords":["kubernetes","PostgreSQL","Queue"],"articleSection":["2022"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html","url":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html","name":"Using Postgres as a Message Queue - JVM Advent","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#primaryimage"},"image":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","datePublished":"2022-12-24T01:01:00+00:00","author":{"@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/e2a44b138b60fcdd955d0cbd27a9d265"},"description":"This article looks into Postgres\u2019 lightweight notification mechanism & discusses how it can be leveraged to implement a simple, but effective push-based message queue.","breadcrumb":{"@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#primaryimage","url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","width":800,"height":800},{"@type":"BreadcrumbList","@id":"https:\/\/www.javaadvent.com\/2022\/12\/using-postgres-as-a-message-queue.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javaadvent.com\/"},{"@type":"ListItem","position":2,"name":"Using Postgres as a Message Queue"}]},{"@type":"WebSite","@id":"https:\/\/www.javaadvent.com\/#website","url":"https:\/\/www.javaadvent.com\/","name":"JVM Advent","description":"The JVM Programming Advent Calendar","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javaadvent.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/e2a44b138b60fcdd955d0cbd27a9d265","name":"Rafael Winterhalter","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g25a2acc71e33aff93eefa5348c37d572","url":"https:\/\/secure.gravatar.com\/avatar\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5888598c5b242c80860406f43f78f1fceb51ee2484fd24c10aeb2cbf1d40045e?s=96&d=retro&r=g","caption":"Rafael Winterhalter"},"description":"Rafael works as a software consultant in Oslo, Norway. He is a proponent of static typing and a JVM enthusiast with particular interest in code instrumentation, concurrency and functional programming. Rafael blogs about software development, regularly presents at conferences and was pronounced a JavaOne Rock Star. When coding outside of his work place, he contributes to a wide range of open source projects and often works on Byte Buddy, a library for simple runtime code generation for the Java virtual machine. For his work, Rafael received a Duke's Choice award, an Oracle groundbreaker award and was elected a Java Champion.","sameAs":["http:\/\/rafael.codes","https:\/\/x.com\/https:\/\/twitter.com\/rafaelcodes"],"url":"https:\/\/www.javaadvent.com\/author\/rafael-wth"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-24.png?fit=800%2C800&ssl=1","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2239,"url":"https:\/\/www.javaadvent.com\/2019\/12\/r2dbc-reactive-relational-database-connectivity.html","url_meta":{"origin":3753,"position":0},"title":"R2DBC &#8211; Reactive relational database connectivity","author":"Nidhin Benjamin","date":"December 22, 2019","format":false,"excerpt":"R2DBC R2DBC is a specification designed for reactive programming \/stream oriented access to SQL databases. It is fully non-blocking. The main initiative of R2dbc is to establish an open standard on reactive programming with SQL databases. This comprises specifications (R2DBC-SPI) and R2DBC drive implementations. Here are the current driver implementations\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":5451,"url":"https:\/\/www.javaadvent.com\/2024\/12\/portable-serverless-functions-with-java-and-quarkus.html","url_meta":{"origin":3753,"position":1},"title":"Portable Serverless Functions with Java (and Quarkus)","author":"Kevin Dubois","date":"December 20, 2024","format":false,"excerpt":"You have probably already heard of serverless functions. If you've played around with them, it might have been on a platform like AWS Lambda, Azure Functions, Google Cloud Functions or similar. The vendors behind these platforms offer solutions specifically for Java as well. The libraries and deployment methodologies are typically\u2026","rel":"","context":"In &quot;2017&quot;","block_context":{"text":"2017","link":"https:\/\/www.javaadvent.com\/category\/2017"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-20.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":5089,"url":"https:\/\/www.javaadvent.com\/2024\/12\/events-love-triangle-in-integration-testing.html","url_meta":{"origin":3753,"position":2},"title":"Events: Love Triangle in Integration Testing","author":"Andres Sacco","date":"December 22, 2024","format":false,"excerpt":"Some years ago, events appeared in the IT world with the idea of decoupling many applications or microservices, improving performance, reducing complexity, and allowing change flows. Some companies adopted this new paradigm instead of the classic synchronic world where the client needed to wait until the provider answered; initially, everything\u2026","rel":"","context":"In &quot;2024&quot;","block_context":{"text":"2024","link":"https:\/\/www.javaadvent.com\/category\/2024"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-22.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":204,"url":"https:\/\/www.javaadvent.com\/2015\/12\/functional-data-structures-in-java-8-with-javaslang.html","url_meta":{"origin":3753,"position":3},"title":"Functional Data Structures in Java 8 with Javaslang","author":"Daniel Dietrich","date":"December 2, 2015","format":false,"excerpt":"Java 8's lambdas (\u03bb) empower us to create wonderful API's. They incredibly increase the expressiveness of the language. Javaslang leveraged lambdas to create various new features based on functional patterns. One of them is a functional collection library that is intended to be a replacement for Java's standard collections. (This\u2026","rel":"","context":"In &quot;2015&quot;","block_context":{"text":"2015","link":"https:\/\/www.javaadvent.com\/category\/2015"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4537,"url":"https:\/\/www.javaadvent.com\/2023\/12\/i-see-events-everywhere-who-will-organize-them.html","url_meta":{"origin":3753,"position":4},"title":"I see events everywhere; who will organize them?","author":"Andres Sacco","date":"December 17, 2023","format":false,"excerpt":"When a new paradigm of communication between applications appears, most developers are excited to migrate and start using it without thinking about the possible problems. Using events instead of classic communication like SOAP, REST, or GraphQL is no exception because it introduces a lot of benefits like decoupling the producers\u2026","rel":"","context":"In &quot;2023&quot;","block_context":{"text":"2023","link":"https:\/\/www.javaadvent.com\/category\/2023"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-17.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-17.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-17.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-17.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3120,"url":"https:\/\/www.javaadvent.com\/2021\/12\/you-need-more-than-containers-a-short-history-of-the-mess-were-in.html","url_meta":{"origin":3753,"position":5},"title":"You need more than containers. A short history of the mess we&#8217;re in.","author":"Markus Eisele","date":"December 7, 2021","format":false,"excerpt":"Lean microservice infrastructures continue to replace classic 3-tier architectures in \u200b\u200benterprise software. Pushing enterprise developers who lived in the fully integrated world of application servers towards dealing with new methodologies and technologies in a cloud-native world. As a matter of fact, distributed architectures differ fundamentally from known, monolithic applications. And\u2026","rel":"","context":"In &quot;2021&quot;","block_context":{"text":"2021","link":"https:\/\/www.javaadvent.com\/category\/2021"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]}],"jetpack_likes_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/3753","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/users\/98"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/comments?post=3753"}],"version-history":[{"count":3,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/3753\/revisions"}],"predecessor-version":[{"id":4436,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/3753\/revisions\/4436"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media\/3227"}],"wp:attachment":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media?parent=3753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/categories?post=3753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/tags?post=3753"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/coauthors?post=3753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}