<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="378178" data-post-id="378178">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstimps" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstimps/120/37213_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstimps
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>As <a class="mention" href="/u/garrison" rel="nofollow">@garrison</a> says, if you’re interested in using FoundationDB, you can use <a href="https://hexdocs.pm/erlfdb/readme.html" rel="noopener nofollow ugc">erlfdb</a> in Elixir. It is API stable and used in serious production systems. Here’s an <a href="https://hexdocs.pm/erlfdb/tutorial-elixir.html" rel="noopener nofollow ugc">Elixir-focused tutorial</a></p>
<p>EctoFDB is more of a batteries-included system, with my opinions built in. I run it in production for a side project, and I believe it works quite well.</p>
<p>Please let me know if you have questions about either one in the EctoFDB thread or in GitHub issues!</p>
<p>BTW excited to see where Hobbes goes. The simulation testing is just as critical as <a class="mention" href="/u/garrison" rel="nofollow">@garrison</a> claims, maybe even moreso <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> . Having a strictly serializable MVCC system embedded in BEAM certainly opens a lot of doors.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378178" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/52">Post #51</a>
	                </div>
	            </div>
              <div id="likers-container-378178" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378178"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #51"></div>
  </section>
</div>
    <div class="postbit" id="378183" data-post-id="378183">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="itekhi" data-post="49" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/itekhi/48/38403_2.png" class="avatar"> itekhi:</div>
<blockquote>
<p>is Hobbes suitable for analytical workloads or it is better to use it as metadata store for a data warehouse? (TBH I don’t really understand for what metadata store is needed and how Hobbes could be used as that</p>
</blockquote>
</aside>
<p>Imagine you’re trying to build something like S3. That is, a distributed filesystem or blob store. The purpose of such a system is to map a small identifier (a file name) to a large blob of contiguous bytes.</p>
<p>The way this is done, generally, is to have a system that associates large blobs (or chunks thereof) to opaque ids, and then have a system that associates file names to those ids. This allows you to quickly perform logical updates against the system without moving around huge blobs of data. It’s an indirection mechanism.</p>
<p>Pretty much every object store you can think of follows this pattern, with a metadata service and a blob storage service. If you want to learn more I’d recommend going back to the classic Google Filesystem (GFS) paper, which is a good early example. Another really good one is the classic Haystack paper from FB, which explains pretty much exactly how to store blobs on disk and why the metadata split is important. They talk a lot about storing metadata in-memory but keep in mind this was before SSDs were cheap.</p>
<p>Hobbes, like FDB, is architecturally amenable to being the metadata store. It’s designed to offer fast, <em>small</em> updates to a large dataset with extremely strong consistency guarantees. It is <em>not</em> designed to offer large updates; even a few megabytes in one transaction would be excessive. This is the correct side of the tradeoff to take for OLTP use-cases where you insert or update a few distant rows/indexes at a time.</p>
<p>This “blob tradeoff” goes right down to the hardware. Hobbes is intended for use on SSDs which can efficiently perform random I/O. But for blob storage you would generally want to use spinning disks because they’re cheaper and the I/O pattern is more sequential. This dichotomy is even more dramatic with SMR drives, which <em>physically cannot</em> perform random writes.</p>
<p>So a design kinda naturally falls out of this: use Hobbes to store metadata (filename mappings) and design a simple “blob storage” server that does nothing but write bytes to spinning disks. The blob storage system can dodge basically all hard distributed systems problems (consistency and so on) because Hobbes provides them by default.</p>
<p>I intend to write something like this soon, once Hobbes is ready.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378183" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/53">Post #52</a>
	                </div>
	            </div>
              <div id="likers-container-378183" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378183"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #52"></div>
  </section>
</div>
    <div class="postbit" id="378191" data-post-id="378191">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Okay, so for an “analytics database” it’s a little more complicated.</p>
<p>First of all, you want to store analytics data in a columnar format. Hobbes is a pure binary/binary KV store underneath, so you can technically store data in whatever format you want. There have been attempts to store columnar data directly in FoundationDB, though I’m not sure if there are any <em>production</em> examples.</p>
<p>However, there are a few things to note:</p>
<ol>
<li>The access patterns for OLAP are generally to write data once, sequentially (updates are rare), and then perform large aggregations over the dataset, which kinda sounds an awful lot like the blob case if you think about it</li>
<li>You have to design a columnar format for the data, which is a lot of work</li>
<li>You have to write an advanced (probably) SQL analytics query engine, which is on the order of a few million lines of tightly optimized low-level code (certainly not Elixir)</li>
</ol>
<p>So due to number 1, you might want to structure your analytics database like a blob store. That is, there is a metadata store tracking which blobs of columnar analytics data are “live” and which ones have been superseded or removed. Snowflake built a hundred-billion-dollar business out of doing this on top of FDB, storing data in (I believe) S3 and specializing in the query engine stuff.</p>
<p>Due to market forces, a number of standards for columnar storage developed. The most notable of these is probably Parquet. The idea here is that a customer can keep their data in Parquet files and then move their “data warehouse” to another provider, which I’m sure companies like Snowflake just loved.</p>
<p>More recently, standards for the query engines themselves have developed. Embedded query engines like Apache DataFusion started to pop up. An emerging winner here is DuckDB, which has distinguished itself with cute branding and a user-friendly standalone CLI. As it turns out, those things are actually very important. You have probably never even heard of DataFusion, have you?</p>
<p>And now, standards for how to maintain the metadata store mapping have also arrived. There are a lot of marketing buzzwords here (try “data lake” and “lakehouse”), but it’s just more standardization at play underneath. DuckDB now actually has its own standard “lakehouse thing” with DuckLake, which indeed uses a metadata store (they call it a “catalog store”) like Postgres to keep track of a bunch of Parquet files.</p>
<p>So, if you were so inclined, you could build an analytics database in Elixir, using Hobbes, like this:</p>
<ul>
<li>Write parquet files to some sort of blob store (perhaps also built with Hobbes)</li>
<li>Keep track of which files are currently “live” using Hobbes as an index</li>
<li>Use DuckDB to perform fast analytical queries on the parquet files</li>
</ul>
<p>And, again, you would get strong correctness, durability, and availability guarantees while solving zero hard distributed systems problems.</p>
<p>That’s the idea.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378191" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/54">Post #53</a>
	                </div>
	            </div>
              <div id="likers-container-378191" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378191"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #53"></div>
  </section>
</div>
    <div class="postbit" id="378270" data-post-id="378270">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Exadra37" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Exadra37/120/9183_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Exadra37
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="itekhi" data-post="49" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/itekhi/48/38403_2.png" class="avatar"> itekhi:</div>
<blockquote>
<p>I am planning to work with lots of analytical (frequently written and aggregated) data,</p>
</blockquote>
</aside>
<p>As the source of truth for the facts you want to persist for later analysis I would recommend an append only log, just like databases do, they call them a WAL (Write Ahead Log).</p>
<p>From the append-only log then you can feed the facts to whatever tools and databases more suited for each use case you need.</p>
<p>This approach doesn’t lock you in to the specifics of a database or tool, thus leaving you with an immutable source of truth for the persisted facts, the append only log, that you can use today, tomorrow, one decade ahead from now, with any tool or database you may need/want.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378270" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/55">Post #54</a>
	                </div>
	            </div>
              <div id="likers-container-378270" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378270"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #54"></div>
  </section>
</div>
    <div class="postbit" id="378274" data-post-id="378274">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Exadra37" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Exadra37/120/9183_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Exadra37
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="garrison" data-post="1" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Hobbes is a scalable, fault-tolerant transactional record store written in Elixir.</p>
</blockquote>
</aside>
<p>If you are building it in pure Elixir then you may need to account for the <code>delayed_write</code> with a default of 2 seconds, that may work against or favourable to you: <a href="https://www.erlang.org/doc/apps/kernel/file.html#open/2" class="inline-onebox" rel="nofollow">file — OTP 29.0.2 (kernel 11.0.2)</a></p>
<pre data-code-wrap="elixir"><code class="lang-elixir">delayed_write - The same as {delayed_write, Size, Delay} with reasonable default values for Size and Delay (roughly some 64 KB, 2 seconds).
</code></pre>
<p>I discovered this while investigating why Mnesia lost all data after restarting my laptop and also found later an issue with an EventLog Elixir library that lost all records inserted to the file during the default two seconds window, when closing a file: <a href="https://github.com/pbudzik/eventlog/issues/1" class="inline-onebox" rel="noopener nofollow ugc">Example in README cannot read the last entry in the append only log · Issue #1 · pbudzik/eventlog · GitHub</a></p>
<p>I also talk about this delayed write issue in this forum post:</p>
<aside class="quote quote-modified" data-post="7" data-topic="19319">
  <div class="title">
    <div class="quote-controls"></div>
    <img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/exadra37/48/9183_2.png" class="avatar">
    <div class="quote-title__text-content">
      <a href="https://forum.elixirforum.com/t/unexpected-behaviour-with-mnesia-not-actually-durable/19319/7" rel="nofollow">Unexpected behaviour with mnesia - not actually durable?</a> <a class="badge-category__wrapper " href="/c/questions-help/questions/53" rel="nofollow"><span data-category-id="53" style="--category-badge-color: #C14BFB; --category-badge-text-color: #000000; --parent-category-badge-color: #C14BFB;" data-parent-category-id="171" data-drop-close="true" class="badge-category --style-square --has-parent" title="Elixir Questions / Help"><span class="badge-category__name">Questions</span></span></a>
    </div>
  </div>
  <blockquote>
    The issue It’s not related with any blocking in Erlang per se… As I mentioned in the post I <a href="https://forum.elixirforum.com/t/mnesia-with-memento-lost-all-records-for-all-tables/36221/38" rel="nofollow">linked</a> previously,  it’s because the BEAM has a default of 2 seconds to write data to the disk when the file is open with the defaults for delayed_write, as per <a href="https://erlang.org/doc/man/file.html#open-2" rel="nofollow">docs </a>: 

delayed_write 
The same as {delayed_write, Size, Delay} with reasonable default values for Size and Delay (roughly some 64 KB, 2 seconds). 

You can confirm this with a script that writes directly to the file system: 
defmodule FileIO do…
  </blockquote>
</aside>

<p><strong>SIde Note</strong>: You may want to read the <a href="http://kafka.apache.org/documentation/#design" rel="noopener nofollow ugc">Kafka design</a> decisions about using a filesystem approach to take advantage of all the low level stuff that Linux has to offer, which may help you with making some decisions on how you use the filesystem from the BEAM. Another interesting option you may want to consider is to disable Linux write cache as I mention in this post: <a href="https://forum.elixirforum.com/t/opinion-on-file-memory-based-event-sourcing-system/24520/21" class="inline-onebox" rel="nofollow">Opinion on file &amp; memory based event sourcing system - #21 by Exadra37</a> .</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378274" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/56">Post #55</a>
	                </div>
	            </div>
              <div id="likers-container-378274" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378274"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #55"></div>
  </section>
</div>
    <div class="postbit" id="378304" data-post-id="378304">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Exadra37" data-post="56" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/exadra37/48/9183_2.png" class="avatar"> Exadra37:</div>
<blockquote>
<p>If you are building it in pure Elixir then you may need to account for the <code>delayed_write</code> with a default of 2 seconds, that may work against or favourable to you</p>
</blockquote>
</aside>
<p>Oh, if only we lived in a world where kernel and filesystem developers didn’t hate us. Then perhaps things could be so easy <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>The BEAM buffering your writes is only the beginning.</p>
<p>Unfortunately the kernel <em>also</em> takes it upon itself to buffer your writes, meaning you need to issue an <code>fsync</code> after writing and before returning a commit. Unless you’re writing a <em>new</em> file, in which case you also <a href="https://danluu.com/file-consistency/" rel="noopener nofollow ugc">need to fsync the parent directory</a>.</p>
<p>Unfortunately the disk can silently corrupt your data, so you need to write a checksum with the data. And you probably want that to be a cryptographic checksum if you’re writing user data (you know, the thing that databases do), otherwise you could be vulnerable to all sorts of weird collision attacks.</p>
<p>Unfortunately <a href="https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/concepts/safety.md#storage-fault-tolerance" rel="noopener nofollow ugc">disks can also misdirect reads and writes</a> to the wrong sectors, meaning that it’s possible for an entirely valid page (with a consistent checksum inside) to be written to <em>or read from</em> the wrong place on disk, silently corrupting the database. So you have to write the page and then keep the checksum as part of the address used to access it, turning the on-disk state into a hash-chained structure.</p>
<p>Unfortunately you still have to store the root hash somewhere, so you have to write several (nearly) identical copies of a superblock, each containing the root. You can then read from and write to those superblock copies like a quorum, which you have to do very carefully because those reads and writes can be misdirected.</p>
<p>Unfortunately even if you do all of the above <code>fsync</code> can still fail, and <a href="https://www.usenix.org/system/files/atc20-rebello.pdf" rel="noopener nofollow ugc">when it fails the OS page cache will lie to you</a> and tell you that the page was actually written. There is no way to make this crash-safe, so you need to bypass the page cache entirely using <code>O_DIRECT</code> and then read back all of your writes directly from the disk to make sure they succeeded.</p>
<p>Unfortunately Erlang does not support <code>O_DIRECT</code> so you need a nif for this.</p>
<p>Unfortunately even if you do all of that your disk can still fail, so you need to perform writes against a set of replicas. There is no way to do that without a consensus algorithm, so you need to implement Paxos/Raft/Viewstamped Replication.</p>
<p>Unfortunately <a href="https://www.usenix.org/system/files/conference/fast18/fast18-alagappan.pdf" rel="noopener nofollow ugc">storage faults can propagate through consensus algorithms</a> in a way that violates fault tolerance, so you have to be very careful to implement consensus properly with respect to disk faults. Which, as it turns out, <em>nobody did</em> back when that paper was published.</p>
<p>Hopefully the value proposition of this work is starting to become clear lol.</p>
<p>This is what I mean when I say that I want to solve these problems once and never again.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378304" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/57">Post #56</a>
	                </div>
	            </div>
              <div id="likers-container-378304" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378304"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #56"></div>
  </section>
</div>
    <div class="postbit" id="378306" data-post-id="378306">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="lud" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lud/120/14382_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  lud
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I guess your database should also email each transaction to the DPO for good measure <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" loading="lazy" width="20" height="20"> Just to be safe!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378306" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/58">Post #57</a>
	                </div>
	            </div>
              <div id="likers-container-378306" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378306"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #57"></div>
  </section>
</div>
    <div class="postbit" id="378311" data-post-id="378311">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I know you’re joking, but it really is storage hardware and APIs specifically that are so unreliable. Byzantine-fault-tolerant systems exist, but servers with ECC memory generally work pretty much all of the time.</p>
<p>Storage hardware, on the other hand, absolutely does exhibit these faults at scale, and even a bit of corruption in the wrong place can break the guarantees of the entire database. Correctness is hard.</p>
<p>Just have a look at what Matrix (the chat service) had to deal with recently when their Postgres indexes were silently corrupted. It’s nightmare fuel.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378311" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/59">Post #58</a>
	                </div>
	            </div>
              <div id="likers-container-378311" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378311"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #58"></div>
  </section>
</div>
    <div class="postbit" id="378312" data-post-id="378312">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Exadra37" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Exadra37/120/9183_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Exadra37
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Lots of insights here that I wasn’t aware of. I knew only about the kernel to also buffer and for the need to use fsync to go around it, but everything else is new to me.</p>
<p>Thanks for the detailed explanation <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378312" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/60">Post #59</a>
	                </div>
	            </div>
              <div id="likers-container-378312" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378312"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #59"></div>
  </section>
</div>
    <div class="postbit" id="378331" data-post-id="378331">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="itekhi" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/itekhi/120/38403_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  itekhi
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you very much for the explanation (I re-read it like 20 times and learned a lot) and papers for me to study!</p>
<aside class="quote no-group" data-username="garrison" data-post="53" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>It’s designed to offer fast, <em>small</em> updates to a large dataset with extremely strong consistency guarantees.</p>
</blockquote>
</aside>
<p>How large can the dataset be? I don’t get what is the limit to the amount of data that can be stored until query/write performance gets bad.</p>
<p>Extremely strong consistency guarantees sounds amazing btw! I’m loving Hobbes more and more</p>
<p>If it’s not much to ask, I understand that there’s also network throughput consideration, that’s why batching exists. But what should you do when massive amount of requests to write small pieces of data come from a lot of sources? Just use Kafka?</p>
<aside class="quote no-group" data-username="garrison" data-post="53" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>I intend to write something like this soon, once Hobbes is ready.</p>
</blockquote>
</aside>
<p>Will be looking forward to it! It will be interesting to see how it works <img src="https://forum.elixirforum.com/images/emoji/apple/eyes.png?v=15" title=":eyes:" class="emoji" alt=":eyes:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="garrison" data-post="54" data-topic="73003">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>There have been attempts to store columnar data directly in FoundationDB</p>
</blockquote>
</aside>
<p>Actually, why I want to study FoundationDB is because it’s really impressive how powerful it is. But it seems really advanced to me, so maybe it’s not the right time for me to dive into it…</p>
<p>I worked with Postgres a lot, so I think TimescaleDB is the way to go for me, btw their Insights tool that uses TDB itself is really impressive with ~3TB of daily data ingest <img src="https://forum.elixirforum.com/images/emoji/apple/face_exhaling.png?v=15" title=":face_exhaling:" class="emoji" alt=":face_exhaling:" loading="lazy" width="20" height="20"></p>
<p>I heard about Parquet quite often, I don’t get though how much data you need to have to have a need for it, as with FDB… (and I indeed didn’t heard of DataFusion <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20">)</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="378331" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/hobbes-a-low-level-distributed-database-for-the-elixir-programming-language/73003/61">Post #60</a>
	                </div>
	            </div>
              <div id="likers-container-378331" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="378331"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #60"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/73003/load_more?page=7">Load more posts (26 remaining)</a>
</div></template></turbo-stream>