156 lines
121 KiB
HTML
Raw Normal View History

2024-02-20 09:23:32 +00:00
<!doctype html>
2025-08-13 03:24:27 +00:00
<html lang="en-GB" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-undefined" data-has-hydrated="false">
2024-02-20 09:23:32 +00:00
<head>
<meta charset="UTF-8">
2025-08-13 03:24:27 +00:00
<meta name="generator" content="Docusaurus v3.8.1">
2025-10-03 05:55:52 +00:00
<title data-rh="true">PostgreSQL | Waku Documentation</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://docs.waku.org/learn/research/benchmarks/postgres-adoption"><meta data-rh="true" property="og:locale" content="en_GB"><meta data-rh="true" name="docusaurus_locale" content="en-GB"><meta data-rh="true" name="docsearch:language" content="en-GB"><meta data-rh="true" name="keywords" content="waku, web3"><meta data-rh="true" name="image" content="https://docs.waku.org/_og/b671a20fd6154a55ddefec1309e744e45b4b6b50.png"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="PostgreSQL | Waku Documentation"><meta data-rh="true" name="description" content="Document that describes why Nim-Waku started to use Postgres and shows some benchmark and comparison results."><meta data-rh="true" property="og:description" content="Document that describes why Nim-Waku started to use Postgres and shows some benchmark and comparison results."><link data-rh="true" rel="icon" href="/theme/image/favicon.ico"><link data-rh="true" rel="canonical" href="https://docs.waku.org/learn/research/benchmarks/postgres-adoption"><link data-rh="true" rel="alternate" href="https://docs.waku.org/learn/research/benchmarks/postgres-adoption" hreflang="en-GB"><link data-rh="true" rel="alternate" href="https://docs.waku.org/learn/research/benchmarks/postgres-adoption" hreflang="x-default"><link rel="alternate icon" type="image/png" href="/theme/image/favicon.png">
<link rel="icon" type="image/svg+xml" href="/theme/image/favicon.svg"><link rel="stylesheet" href="/assets/css/styles.f0961b96.css">
2025-10-27 23:35:15 +00:00
<script src="/assets/js/runtime~main.4a8ea766.js" defer="defer"></script>
<script src="/assets/js/main.cd8c4833.js" defer="defer"></script>
2025-08-13 03:24:27 +00:00
<meta property="og:image" content="https://docs.waku.org/_og/b671a20fd6154a55ddefec1309e744e45b4b6b50.png"><meta name="twitter:image" content="https://docs.waku.org/_og/b671a20fd6154a55ddefec1309e744e45b4b6b50.png"></head>
2024-02-20 09:23:32 +00:00
<body class="navigation-with-keyboard">
2025-08-13 03:24:27 +00:00
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></symbol>
</defs></svg>
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="/theme/image/logo-black.svg"><link rel="preload" as="image" href="/theme/image/logo.svg"><style data-emotion="css-global 3rtehh">.lsd-button{width:auto;cursor:pointer;padding:6px 24px;}.lsd-button--disabled{cursor:default;opacity:0.34;}.lsd-button--large{padding:10px 40px;}.lsd-button--medium{padding:6px 24px;}.lsd-button--small{padding:6px 12px;}.lsd-button:hover:not(.lsd-button--disabled) .lsd-button__text{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-button--with-icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-button__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;}.lsd-button--large.lsd-button--with-icon{padding:10px 0px 10px 18px;}.lsd-button--large.lsd-button--with-icon .lsd-button__icon{width:42px;}.lsd-button--medium.lsd-button--with-icon{padding:6px 0px 6px 14px;}.lsd-button--medium.lsd-button--with-icon .lsd-button__icon{width:38px;}.lsd-button--small.lsd-button--with-icon{padding:6px 0px 6px 12px;}.lsd-button--small.lsd-button--with-icon .lsd-button__icon{width:34px;}.lsd-button--outlined{background:none;border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--outlined .lsd-button__text{color:rgb(var(--lsd-text-primary));}.lsd-button--filled{background:rgb(var(--lsd-surface-secondary));border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--filled .lsd-button__text{color:rgb(var(--lsd-text-secondary));}</style><style data-emotion="css-global 10bahxd">.lsd-icon-button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;cursor:pointer;background:none;padding:0;border:1px solid rgb(var(--lsd-border-primary));}.lsd-icon-button--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-icon-button--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-icon-button--disabled{opacity:0.34;cursor:default;}.lsd-icon-button--large{width:40px;height:40px;}.lsd-icon-button--medium{width:32px;height:32px;}.lsd-icon-button--small{width:28px;height:28px;}</style><style data-emotion="css-global icqph9">.lsd-icon-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}.lsd-icon-button-group--outlined .lsd-icon-button:not(:last-child){border-right:none;}</style><style data-emotion="css-global 1f43ub2">body *{font-family:var(--lsd-typography-generic-font-family);}.lsd-typography{color:rgb(var(--lsd-text-primary));}.lsd-typography--sans-serif,.lsd-typography--sans-serif *{font-family:sans-serif;}.lsd-typography--serif,.lsd-typography--serif *{font-family:serif;}.lsd-typography--monospace,.lsd-typography--monospace *{font-family:monospace;}.lsd-typography--display1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display1-fontWeight);font-size:var(--lsd
2024-02-20 09:23:32 +00:00
.lsd-dropdown--error
) .lsd-dropdown__trigger:hover .lsd-dropdown__option-label,.lsd-dropdown:not(.lsd-dropdown--disabled):not(
.lsd-dropdown--error
2025-10-03 05:55:52 +00:00
) .lsd-dropdown__trigger:focus .lsd-dropdown__option-label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown__label{display:block;}.lsd-dropdown__button-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-dropdown__trigger{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;border:none;cursor:pointer;background:none;}.lsd-dropdown__trigger:focus{outline:none;}.lsd-dropdown__option-label{cursor:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lsd-dropdown__icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;gap:8px;}.lsd-dropdown__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-dropdown__supporting-text{margin:6px 14px;}.lsd-dropdown--error .lsd-dropdown__option-label{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-dropdown--disabled{opacity:0.34;cursor:initial;}.lsd-dropdown--large{width:208px;}.lsd-dropdown--large.lsd-dropdown--error{width:230px;}.lsd-dropdown--large .lsd-dropdown__label{margin:0 0 6px 18px;}.lsd-dropdown--large .lsd-dropdown__button-container{height:40px;}.lsd-dropdown--large .lsd-dropdown__trigger{padding:10px 0px 10px 18px;}.lsd-dropdown--large .lsd-dropdown__icons{padding:0px 14px;}.lsd-dropdown--medium{width:188px;}.lsd-dropdown--medium.lsd-dropdown--error{width:210px;}.lsd-dropdown--medium .lsd-dropdown__label{margin:0 0 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__button-container{height:32px;}.lsd-dropdown--medium .lsd-dropdown__trigger{padding:6px 0px 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__icons{padding:0px 12px;}.lsd-dropdown--small{width:164px;}.lsd-dropdown--small.lsd-dropdown--error{width:186px;}.lsd-dropdown--small .lsd-dropdown__label{margin:0 0 6px 12px;}.lsd-dropdown--small .lsd-dropdown__button-container{height:28px;}.lsd-dropdown--small .lsd-dropdown__trigger{padding:6px 0px 6px 12px;}.lsd-dropdown--small .lsd-dropdown__icons{padding:0px 10px;}.lsd-dropdown--outlined .lsd-dropdown__button-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown--underlined .lsd-dropdown__button-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global w2g5fy">.lsd-dropdown-item{width:100%;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled){cursor:pointer;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus{outline:none;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover .lsd-dropdown-item__label,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus .lsd-dropdown-item__label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown-item__label{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lsd-dropdown-item--disabled{opacity:0.34;}.lsd-dropdown-item__icon{margin-right:18px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-dropdown-item--small{padding:5px 9px;height:28px;}.l
2025-08-13 03:24:27 +00:00
<p>The <em>Nim Waku Node</em>, <em>nwaku</em>, has the capability of archiving messages until a certain limit (e.g. 30 days) so that other nodes can synchronize their message history throughout the <em>Store</em> protocol.</p>
<p>The <em>nwaku</em> originally used <em>SQLite</em> to archive messages but this has an impact on the node. <em>Nwaku</em> is single-threaded and therefore, any <em>SQLite</em> operation impacts the performance of other protocols, like <em>Relay.</em></p>
<p>Therefore, the <em>Postgres</em> adoption is needed to enhance that.</p>
<p><a href="https://github.com/waku-org/nwaku/issues/1888" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/nwaku/issues/1888</a></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="how-to-connect-the-nwaku-to-postgres">How to connect the <em>nwaku</em> to <em>Postgres</em><a href="#how-to-connect-the-nwaku-to-postgres" class="hash-link" aria-label="Direct link to how-to-connect-the-nwaku-to-postgres" title="Direct link to how-to-connect-the-nwaku-to-postgres"></a></h2>
<p>Simply pass the next parameter to <em>nwaku</em></p>
<div class="language-bash codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:rgba(var(--lsd-surface-secondary), 0.08)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">--store-message-db-url=&quot;postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/postgres</span><br></span></code></pre></div></div>
<p>Notice that this only makes sense if the <em>nwaku</em> has the <em>Store</em> protocol mounted</p>
<div class="language-bash codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:rgba(var(--lsd-surface-secondary), 0.08)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">--store=true</span><br></span></code></pre></div></div>
<p>(start the <em>nwaku</em> node with <code>--help</code> parameter for more <em>Store</em> options)</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="examples-of-nwaku-using-postgres">Examples of <em>nwaku</em> using <em>Postgres</em><a href="#examples-of-nwaku-using-postgres" class="hash-link" aria-label="Direct link to examples-of-nwaku-using-postgres" title="Direct link to examples-of-nwaku-using-postgres"></a></h2>
<p><a href="https://github.com/waku-org/nwaku-compose" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/nwaku-compose</a></p>
<p><a href="https://github.com/waku-org/test-waku-query" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/test-waku-query</a></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="stress-tests">Stress tests<a href="#stress-tests" class="hash-link" aria-label="Direct link to Stress tests" title="Direct link to Stress tests"></a></h2>
<p>The following repository was created as a tool to stress and compare performance between <em>nwaku</em>+<em>Postgres</em> and <em>nwaku</em>+<em>SQLite</em>:</p>
<p><a href="https://github.com/waku-org/test-waku-query" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/test-waku-query</a></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="insert-test-results">Insert test results<a href="#insert-test-results" class="hash-link" aria-label="Direct link to Insert test results" title="Direct link to Insert test results"></a></h3>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="maximum-insert-throughput">Maximum insert throughput<a href="#maximum-insert-throughput" class="hash-link" aria-label="Direct link to Maximum insert throughput" title="Direct link to Maximum insert throughput"></a></h4>
<p><strong>Scenario</strong></p>
<ul>
<li>1 node subscribed to pubsubtopic x and the <em>Store</em> protocol mounted.</li>
<li>n nodes connected to the “store” node, and publishing messages simultaneously to pubsubtopic x.</li>
<li>All nodes running locally in a <em>Dell Latitude 7640</em>.</li>
<li>Each published message is fixed, 1.4 KB: <a href="https://github.com/waku-org/test-waku-query/blob/master/sh/publish_one_client.sh" target="_blank" rel="noopener noreferrer">publish_one_client.sh</a></li>
<li>The next script is used to simulate multiple nodes publishing messages: <a href="https://github.com/waku-org/test-waku-query/blob/fe7061a21eb14395e723402face755c826077aec/sh/publish_multiple_clients.sh" target="_blank" rel="noopener noreferrer">publish_multiple_clients.sh</a></li>
</ul>
<p><strong>Sought goal</strong></p>
<p>Find out the maximum number of concurrent inserts that both <em>SQLite</em> and <em>Postgres</em> could support, and check whether <em>Postgres</em> behaves better than <em>SQLite</em> or not.</p>
<p><strong>Conclusion</strong></p>
<p>Messages are lost after a certain threshold, and this message loss is due to limitations in the <em>Relay</em> protocol (GossipSub - libp2p.)</p>
<p>For example, if we set 30 nodes publishing 300 messages simultaneously, then 8997 rows were stored and not the expected 9000, in both <em>SQLite</em> and <em>Postgres</em> databases.</p>
<p>The reason why few messages were lost is because the message rate was higher than the <em>relay</em> protocol can support, and therefore a few messages were not stored. In this example, the test took 38.8, and therefore, the node was receiving 232 msgs/sec, which is much more than the normal rate a node will work with, which is ~10 msgs/sec (rate extracted from Grafanas stats for the <em>status.prod</em> fleet.)</p>
<p>As a conclusion, the bottleneck is within the <em>Relay</em> protocol itself and not the underlying databases. Or, in other words, both <em>SQLite</em> and <em>Postgres</em> can support the maximum insert rate a Waku node will operate within normal conditions.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="query-test-results-jmeter">Query test results (jmeter)<a href="#query-test-results-jmeter" class="hash-link" aria-label="Direct link to Query test results (jmeter)" title="Direct link to Query test results (jmeter)"></a></h3>
<p>In this case, we are comparing <em>Store</em> performance by means of Rest service.</p>
<p><strong>Scenario</strong></p>
<ul>
<li>node_a: one <em>nwaku</em> node with <em>Store</em> and connected to <em>Postgres.</em></li>
<li>node_b: one <em>nwaku</em> node with <em>Store</em> and using <em>SQLite</em>.</li>
<li>Both <em>Postgres</em> and <em>SQLite</em> contain +1 million rows.</li>
<li>node_c: one <em>nwaku</em> node with <em>REST</em> enabled and acting as a <em>Store client</em> for node_a.</li>
<li>node_d: one <em>nwaku</em> node with <em>REST</em> enabled and acting as a <em>Store client</em> for node_b.</li>
<li>With <em>jmeter</em>, 10 users make <em>REST</em> <em>Store</em> requests concurrently to each of the “rest” nodes (node_c and node_d.)</li>
<li>All <em>nwaku</em> nodes running statusteam/nim-waku:v0.19.0</li>
</ul>
<p><a href="https://github.com/waku-org/test-waku-query/blob/master/docker/jmeter/http_store_requests.jmx" target="_blank" rel="noopener noreferrer">This</a> is the <em>jmeter</em> project used.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Using jmeter" src="/assets/images/using-jmeter-fb15a8f1842c5307ac9c375518cf14d0.png" width="1178" height="458" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p><em>Results</em></p>
<p>With this, the <em>node_b</em> brings a higher throughput than the <em>node_a</em> and that indicates that the node that uses SQLite performs better. The following shows the measures taken by <em>jmeter</em> with regard to the REST requests.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="jmeter results" src="/assets/images/jmeter-results-b7c1925776dc6b56d42d959250eefe05.png" width="1475" height="73" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="query-test-results-only-store-protocol">Query test results (only Store protocol)<a href="#query-test-results-only-store-protocol" class="hash-link" aria-label="Direct link to Query test results (only Store protocol)" title="Direct link to Query test results (only Store protocol)"></a></h3>
<p>In this test suite, only the Store protocol is being analyzed, i.e. without REST. For that, a go-waku node is used, which acts as <em>Store</em> client. On the other hand, we have another go-waku app that publishes random <em>Relay</em> messages periodically. Therefore, this can be considered a more realistic approach.</p>
<p>The following diagram shows the topology used:</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Topology" src="/assets/images/topology-only-store-protocol-4c1704db48f330abda7f925618c485b4.png" width="1270" height="740" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p>For that, the next apps were used:</p>
<ol>
<li><a href="https://github.com/alrevuelta/waku-publisher/tree/9fb206c14a17dd37d20a9120022e86475ce0503f" target="_blank" rel="noopener noreferrer">Waku-publisher.</a> This app can publish Relay messages with different numbers of clients</li>
<li><a href="https://github.com/Ivansete-status/waku-store-query-generator/tree/19e6455537b6d44199cf0c8558480af5c6788b0d" target="_blank" rel="noopener noreferrer">Waku-store-query-generator</a>. This app is based on the Waku-publisher but in this case, it can spawn concurrent go-waku Store clients.</li>
</ol>
<p>That topology is defined in <a href="https://github.com/waku-org/test-waku-query/blob/7090cd125e739306357575730d0e54665c279670/docker/docker-compose-manual-binaries.yml" target="_blank" rel="noopener noreferrer">this</a> docker-compose file.</p>
<p>Notice that the two <code>nwaku</code> nodes run the very same version, which is compiled locally.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="comparing-archive-sqlite--postgres-performance-in-nwaku-b6dd6899">Comparing archive SQLite &amp; Postgres performance in <a href="https://github.com/waku-org/nwaku/tree/b6dd6899030ee628813dfd60ad1ad024345e7b41" target="_blank" rel="noopener noreferrer">nwaku-b6dd6899</a><a href="#comparing-archive-sqlite--postgres-performance-in-nwaku-b6dd6899" class="hash-link" aria-label="Direct link to comparing-archive-sqlite--postgres-performance-in-nwaku-b6dd6899" title="Direct link to comparing-archive-sqlite--postgres-performance-in-nwaku-b6dd6899"></a></h4>
<p>The next results were obtained by running the docker-compose-manual-binaries.yml from <a href="https://github.com/waku-org/test-waku-query/tree/c07807597faa781ae6c8c32eefdf48ecac03a7ba" target="_blank" rel="noopener noreferrer">test-waku-query-c078075</a> in the sandbox machine (metal-01.he-eu-hel1.misc.wakudev.status.im.)</p>
<p><strong>Scenario 1</strong></p>
<p><strong>Store rate:</strong> 1 user generating 1 store-req/sec.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p>In this case, we can see that the SQLite performance is better regarding the store requests.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-24602d6973d24be6b019dad1777bb987.png" width="1820" height="306" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-f40e2f9ea1b96e1288c924f5c600d948.png" width="1820" height="306" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p>The following graph shows how the <em>SQLite</em> node has blocking periods whereas the <em>Postgres</em> always gives a steady rate.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Num queries per minute" src="/assets/images/num-queries-per-minute-6a54abcc873ba4ec4a30058499435bbd.png" width="1828" height="240" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p><strong>Scenario 2</strong></p>
<p><strong>Store rate:</strong> 10 users generating 1 store-req/sec.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p>In this case, is more evident that the <em>SQLite</em> performs better.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-2-46dc8832866df6316c3c4198f72f7933.png" width="1829" height="311" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-2-ca8dd4d4dd040e11639ec9902494d762.png" width="1826" height="533" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p><strong>Scenario 3</strong></p>
<p><strong>Store rate:</strong> 25 users generating 1 store-req/sec.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p>In this case, the performance is similar regarding the timings. The store rate is bigger in <em>SQLite</em> and <em>Postgres</em> keeps the same level as in scenario 2.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-3-b0fea4a8261185b481d49f9ced83e3e5.png" width="1826" height="305" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-3-5ecfd6bfc2de09c5453c4a5f6ea2ef5c.png" width="1826" height="535" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="comparing-archive-sqlite--postgres-performance-in-nwaku-b452ed8">Comparing archive SQLite &amp; Postgres performance in <a href="https://github.com/waku-org/nwaku/tree/b452ed865466a33b7f5b87fa937a8471b28e466e" target="_blank" rel="noopener noreferrer">nwaku-b452ed8</a><a href="#comparing-archive-sqlite--postgres-performance-in-nwaku-b452ed8" class="hash-link" aria-label="Direct link to comparing-archive-sqlite--postgres-performance-in-nwaku-b452ed8" title="Direct link to comparing-archive-sqlite--postgres-performance-in-nwaku-b452ed8"></a></h4>
<p>This nwaku commit is after a few <strong>Postgres</strong> optimizations were applied.</p>
<p>The next results were obtained by running the docker-compose-manual-binaries.yml from <a href="https://github.com/waku-org/test-waku-query/tree/c07807597faa781ae6c8c32eefdf48ecac03a7ba" target="_blank" rel="noopener noreferrer">test-waku-query-c078075</a> in the sandbox machine (metal-01.he-eu-hel1.misc.wakudev.status.im.)</p>
<p><strong>Scenario 1</strong></p>
<p><strong>Store rate</strong> 1 user generating 1 store-req/sec. Notice that the current Store query used generates pagination which provokes more subsequent queries than the 1 req/sec that would be expected without pagination.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-4-f6d6bb7844c5da6d8b32b7a0ca04e9dd.png" width="1831" height="306" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-4-03ae15c83b1b754a6716b8d25593e7be.png" width="1831" height="533" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p>It cannot be appreciated but the average <em><strong><strong>Store</strong></strong></em> time was 11ms.</p>
<p><strong>Scenario 2</strong></p>
<p><strong>Store rate:</strong> 10 users generating 1 store-req/sec. Notice that the current Store query used generates pagination which provokes more subsequent queries than the 10 req/sec that would be expected without pagination.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-5-8a5fc95666e514142280e7b31332860a.png" width="1832" height="311" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-5-eae87929d2d1e5a8399131d2492664f3.png" width="1828" height="537" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p><strong>Scenario 3</strong></p>
<p><strong>Store rate:</strong> 25 users generating 1 store-req/sec. Notice that the current Store query used generates pagination which provokes more subsequent queries than the 25 req/sec that would be expected without pagination.</p>
<p><strong>Relay rate:</strong> 1 user generating 10msg/sec, 10KB each.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution" src="/assets/images/insert-time-dist-6-c296f68fc41d94a05facc5aa08bfef14.png" width="1834" height="311" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution" src="/assets/images/query-time-dist-6-9328594b3f669f5d217a7e4e70a997d9.png" width="1828" height="540" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="conclusions">Conclusions<a href="#conclusions" class="hash-link" aria-label="Direct link to Conclusions" title="Direct link to Conclusions"></a></h4>
<p>After comparing both systems, <em>SQLite</em> performs much better than <em>Postgres</em> However, a benefit of using <em>Postgres</em> is that it performs asynchronous operations, and therefore doesnt consume CPU time that would be better invested in <em>Relay</em> for example.</p>
<p>Remember that <em>nwaku</em> is single-threaded and <em>chronos</em> performs orchestration among a bunch of async tasks, and therefore it is not a good practice to block the whole <em>nwaku</em> process in a query, as happens with <em>SQLite</em></p>
<p>After applying a few <em>Postgres</em> enhancements, it can be noticed that the use of concurrent <em>Store</em> queries doesnt go below the 250ms barrier. The reason for that is that most of the time is being consumed in <a href="https://github.com/waku-org/nwaku/blob/6da1aeec5370bb1c116509e770178cca2662b69c/waku/common/databases/db_postgres/dbconn.nim#L124" target="_blank" rel="noopener noreferrer">this point</a>. The <code>libpqisBusy()</code> function indicates that the connection is still busy even the queries finished.</p>
<p>Notice that we usually have a rate below 1100 req/minute in <em>status.prod</em> fleet (checked November 7, 2023.)</p>
<hr>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="multiple-nodes--one-single-database">Multiple nodes &amp; one single database<a href="#multiple-nodes--one-single-database" class="hash-link" aria-label="Direct link to Multiple nodes &amp; one single database" title="Direct link to Multiple nodes &amp; one single database"></a></h3>
<p>This study aims to look for possible issues when having only one single database while several Waku nodes insert or retrieve data from it.
The following diagram shows the scenery used for such analysis.</p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="digram_multiple_nodes_one_database" src="/assets/images/digram_multiple_nodes_one_database-f503210c733fbeb8a572f9f6ccd81adf.png" width="1581" height="867" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p>There are three nim-waku nodes that are connected to the same database and all of them are trying to write messages to the same <em>PostgreSQL</em> instance. With that, it is very common to see errors like:</p>
<div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:rgba(var(--lsd-surface-secondary), 0.08)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ERR 2023-11-27 13:18:07.575+00:00 failed to insert message topics=&quot;waku archive&quot; tid=2921 file=archive.nim:111 err=&quot;error in runStmt: error in dbConnQueryPrepared calling waitQueryToFinish: error in query: ERROR: duplicate key value violates unique constraint \&quot;messageindex\&quot;\nDETAIL: Key (storedat, id, pubsubtopic)=(1701091087417938405, 479c95bbf74222417abf76c7f9c480a6790e454374dc4f59bbb15ca183ce1abd, /waku/2/default-waku/proto) already exists.\n</span><br></span></code></pre></div></div>
<p>The <code>db-postgres-hammer</code> is aimed to stress the database from the <code>select</code> point of view. It performs <code>N</code> concurrent <code>select</code> queries with a certain rate.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="results">Results<a href="#results" class="hash-link" aria-label="Direct link to Results" title="Direct link to Results"></a></h4>
<p>The following results were obtained by using the sandbox machine (metal-01.he-eu-hel1.misc.wakudev) and running nim-waku nodes from <a href="https://github.com/waku-org/nwaku/tree/b452ed865466a33b7f5b87fa937a8471b28e466e" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/nwaku/tree/b452ed865466a33b7f5b87fa937a8471b28e466e</a> and using the <code>test-waku-query</code> project from <a href="https://github.com/waku-org/test-waku-query/tree/fef29cea182cc744c7940abc6c96d38a68739356" target="_blank" rel="noopener noreferrer">https://github.com/waku-org/test-waku-query/tree/fef29cea182cc744c7940abc6c96d38a68739356</a></p>
<p>The following shows the results</p>
<ol>
<li>Two <code>nwaku-postgres-additional</code> inserting messages plus 50 <code>db-postgres-hammer</code> making 10 <code>selects</code> per second.</li>
</ol>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution Postgres" src="/assets/images/insert-time-dist-postgres-938248325bab6bd74a1945193f88a95c.png" width="924" height="288" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<p></p><div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution Postgres" src="/assets/images/query-time-dist-postgres-63483fc4a94701ff82c19fc292d00f5c.png" width="913" height="307" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div><p></p>
<ol start="2">
<li>Five <code>nwaku-postgres-additional</code> inserting messages plus 50 <code>db-postgres-hammer</code> making 10 <code>selects</code> per second.
<div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution Postgres" src="/assets/images/insert-time-dist-postgres-2-78f1bb4fc86aba4604ceda390a37dc96.png" width="913" height="307" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div>
<div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution Postgres" src="/assets/images/query-time-dist-postgres-2-347ba236b22fccce5efa56b29dae2021.png" width="913" height="307" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div></li>
</ol>
<p>In this case, the insert time gets more spread because the insert operations are shared amongst five more nodes. The <em>Store</em> query time remains the same on average.</p>
<ol start="3">
<li>Five <code>nwaku-postgres-additional</code> inserting messages plus 100 <code>db-postgres-hammer</code> making 10 <code>selects</code> per second.
2024-02-20 09:23:32 +00:00
This case is similar to 2. but stressing more the database.
2025-08-13 03:24:27 +00:00
<div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Insert time distribution Postgres" src="/assets/images/insert-time-dist-postgres-3-8c6c424e8e30dd9201539a6eba942857.png" width="917" height="308" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div>
<div class="wrapper_SWrM active_qZD5"><img decoding="async" loading="lazy" alt="Query time distribution Postgres" src="/assets/images/query-time-dist-postgres-3-ff3612d13d631359595fbc395976a237.png" width="909" height="313" class="img_ev3q"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917M2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167"></path></svg></div></button></div></li>
2025-10-03 05:55:52 +00:00
</ol></div><footer class="theme-doc-footer docusaurus-mt-lg"><div class="row margin-top--sm theme-doc-footer-edit-meta-row"><div class="col"><a href="https://github.com/waku-org/docs.waku.org/tree/develop/docs/learn/research/benchmarks/postgres-adoption.md" target="_blank" rel="noreferrer noopener" class="theme-edit-this-page"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="#fff" fill-rule="evenodd" d="m12.707 2.393.9.9c.526.52.526 1.367 0 1.887L4.787 14H2v-2.787l6.933-6.94 1.887-1.88c.52-.52 1.367-.52 1.887 0M3.333 12.667l.94.04 6.547-6.554-.94-.94-6.547 6.547z" clip-rule="evenodd"></path></svg></div><span class="lsd-typography lsd-typography--body2">Edit this page</span></a></div><div class="col lastUpdated_JAkA"></div></div></footer></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/learn/research/"><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="M11.667 6.417h-7.1L7.83 3.156 7 2.333 2.334 7 7 11.667l.823-.823-3.255-3.26h7.099z"></path></svg></div><span class="lsd-typography lsd-typography--body2 pagination-nav__label">Research</span></a><a class="pagination-nav__link pagination-nav__link--next" href="/learn/research/benchmarks/test-results-summary"><span class="lsd-typography lsd-typography--body2 pagination-nav__label">Performance Benchmarks and Test Reports</span><div class="icon_S7Kx m_thRi"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14"><path fill="#fff" d="m7 2.334-.823.822 3.255 3.26H2.333v1.167h7.1l-3.256 3.261.823.823L11.667 7z"></path></svg></div></a></nav></div></div><div class="gap1_XuuQ"></div><div class="toc_pP_5"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#introduction" class="table-of-contents__link toc-highlight">Introduction</a></li><li><a href="#how-to-connect-the-nwaku-to-postgres" class="table-of-contents__link toc-highlight">How to connect the <em>nwaku</em> to <em>Postgres</em></a></li><li><a href="#examples-of-nwaku-using-postgres" class="table-of-contents__link toc-highlight">Examples of <em>nwaku</em> using <em>Postgres</em></a></li><li><a href="#stress-tests" class="table-of-contents__link toc-highlight">Stress tests</a><ul><li><a href="#insert-test-results" class="table-of-contents__link toc-highlight">Insert test results</a></li><li><a href="#query-test-results-jmeter" class="table-of-contents__link toc-highlight">Query test results (jmeter)</a></li><li><a href="#query-test-results-only-store-protocol" class="table-of-contents__link toc-highlight">Query test results (only Store protocol)</a></li><li><a href="#multiple-nodes--one-single-database" class="table-of-contents__link toc-highlight">Multiple nodes &amp; one single database</a></li></ul></li></ul></div></div></div></div></main></div></div></div><footer class="footer"><div class="container container-fluid firstRow_ar1q"><div class="footer__bottom text--center"><div class="margin-bottom--sm"><a class="footerLogoLink_BH7S" href="/"><img src="/theme/image/logo.svg" alt="Waku" class="themedImage_kfRS themedImage--light_BL8e footer__logo" width="22"><img src="/theme/image/logo.svg" alt="Waku" class="themedImage_kfRS themedImage--dark_OvIx footer__logo" width="22"></a></div><div class="footer__copyright">Waku</div></div><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://twitter.com/waku_org/" target="_blank" rel="noopener noreferrer" class="footer__link-item">X<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://discord.waku.org/" targe
2024-02-20 09:23:32 +00:00
</body>
</html>