<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Golang on Mia Heidenstedt</title><link>https://heidenstedt.org/tags/golang/</link><description>Recent
content
in Golang on Mia Heidenstedt</description><generator>
Hugo</generator><language>en</language><lastBuildDate>Thu, 16 Apr 2026 07:56:47 +0000</lastBuildDate><atom:link href="https://heidenstedt.org/tags/golang/index.xml" rel="self" type="application/rss+xml"/><item><title>How to effectively write quality code with AI</title><link>https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/</link><pubDate>Fri, 06 Feb 2026 17:35:31 +0000</pubDate><guid>https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><h2 id="1-establish-a-clear-vision"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#1-establish-a-clear-vision">1 Establish a Clear Vision</a></h2><p>You are a human, you know how this world behaves, how your team and colleagues behave, and what your users expect. You have experienced the world, and you want to work together with a system that has no experience in this world you live in. Every decision in your project that you don&rsquo;t take and document will be taken for you by the AI.</p>
<p>Your responsibility of delivering quality code cannot be met if not even you know where long-lasting and difficult-to-change decisions are taken.<br>
You must know what parts of your code need to be thought through and what must be vigorously tested.</p>
<p>Think about and discuss the architecture, interfaces, data structures, and algorithms you want to use.
Think about how to test and validate your code to these specifications.</p>
<h2 id="2-maintain-precise-documentation"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#2-maintain-precise-documentation">2 Maintain Precise documentation</a></h2><p>You need to communicate to the AI in detail what you want to achieve, otherwise it will result in code that is unusable for your purpose.</p>
<p>Other developers also need to communicate this information to the AI. That makes it efficient to write as much documentation as practical in a standardized format and into the code repository itself.</p>
<p>Document the requirements, specifications, constraints, and architecture of your project in detail.<br>
Document your coding standards, best practices, and design patterns.<br>
Use flowcharts, UML diagrams, and other visual aids to communicate complex structures and workflows.<br>
Write pseudocode for complex algorithms and logic to guide the AI in understanding your intentions.</p>
<h2 id="3-build-debug-systems-that-aid-the-ai"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#3-build-debug-systems-that-aid-the-ai">3 Build debug systems that aid the AI</a></h2><p>Develop efficient debug systems for the AI to use, reducing the need for multiple expensive CLI commands or browsers to verify code functionality. This will save time and resources while simplifying the process for the AI to identify and resolve code issues.</p>
<p>For example: Build a system that collects logs from all nodes in a distributed system and provides abstracted information like &ldquo;The Data was send to all nodes&rdquo;, &ldquo;The Data X is saved on Node 1 but not on Node 2&rdquo;.</p>
<h2 id="4-mark-code-review-levels"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#4-mark-code-review-levels">4 Mark code review levels</a></h2><p>Not all code is equally important. Some parts of your codebase are critical and need to be reviewed with extra care. Other parts are less important and can be generated with less oversight.</p>
<p>Use a system that allows you to mark how thoroughly each function has been reviewed.</p>
<p>For example you can use a prompt that will let the AI put the comment <code>//A</code> behind functions it wrote to indicate that the function has been written by an AI and is not yet reviewed by a human.</p>
<h2 id="5-write-high-level-specifications-and-test-by-yourself"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#5-write-high-level-specifications-and-test-by-yourself">5 Write high level specifications and test by yourself</a></h2><p>AIs will cheat and use shortcuts eventually. They will write mocks, stubs, and hard coded values to make the code tests succeed while the code itself is not working and most of the time dangerous. Often AIs will adapt or outright delete test code to let the code pass tests.</p>
<p>You must discourage this behavior by writing property based high level specification tests yourself. Build them in a way that makes it hard for the AI to cheat without having big code segments dedicated to it.<br>
For example, use property based testing, restart the server and check in between if the database has the correct values.</p>
<p>Separate these test so the AI cannot edit them and prompt the AI not to change them.</p>
<h2 id="6-write-interface-tests-in-a-separate-context"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#6-write-interface-tests-in-a-separate-context">6 Write interface tests in a separate context</a></h2><p>Let an AI write property based interface tests for the expected behavior with as little context of the rest of the code as possible.<br>
This will generate tests that are uninfluenced by the &ldquo;implementation AI&rdquo; which will prevent the tests from being adapted to the implementation in a way that makes them useless or less effective.</p>
<p>Separate these tests so the AI cannot edit them without approval and prompt the AI not to change them.</p>
<h2 id="7-use-strict-linting-and-formatting-rules"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#7-use-strict-linting-and-formatting-rules">7 Use strict linting and formatting rules</a></h2><p>Use strict linting and formatting rules to ensure code quality and consistency. This will help you and your AI to find issues early.</p>
<h2 id="8-use-context-specific-coding-agent-prompts"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#8-use-context-specific-coding-agent-prompts">8 Use context specific coding agent prompts</a></h2><p>Save time and money by utilizing path specific coding agent prompts like <a href="https://www.anthropic.com/engineering/claude-code-best-practices#:~:text=Create%20CLAUDE.md%20files">CLAUDE.md</a>.</p>
<p>You can generate them automatically which will give your AI information it would otherwise as to create from scratch every time.</p>
<p>Try to provide as much high level information as practical, such as coding standards, best practices, design patterns, and specific requirements for the project. This will help the AI to generate code that is more aligned with your expectations and will reduce lookup time and cost.</p>
<h2 id="9-find-and-mark-functions-that-have-a-high-security-risk"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#9-find-and-mark-functions-that-have-a-high-security-risk">9 Find and mark functions that have a high security risk</a></h2><p>Identify and mark functions that have a high security risk, such as authentication, authorization, and data handling. These functions should be reviewed and tested with extra care and in such a way that a human has comprehended the logic of the function in all its dimensions and is confident about its correctness and safety.</p>
<p>Make this explicit with a comment like <code>//HIGH-RISK-UNREVIEWED</code> and <code>//HIGH-RISK-REVIEWED</code> to make sure that other developers are aware of the importance of these functions and will review them with extra care.</p>
<p>Make sure that the AI is instructed to change the review state of these functions as soon as it changes a single character in the function.<br>
Developers must make sure that the status of these functions is always correct.</p>
<h2 id="10-reduce-code-complexity-where-possible"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#10-reduce-code-complexity-where-possible">10 Reduce code complexity where possible</a></h2><p>Aim to reduce the complexity of the generated code where possible. Each single line of code will eat up your context window and make it harder for the AI and You to keep track of the overall logic of your code.<br>
Each avoidable line of code is costing energy, money and probability of future unsuccessful AI tasks.</p>
<h2 id="11-explore-problems-with-experiments-and-prototypes"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#11-explore-problems-with-experiments-and-prototypes">11 Explore problems with experiments and prototypes</a></h2><p>AI written code is cheap, use this to your advantage by exploring different solutions to a problem with experiments and prototypes with minimal specifications. This will allow you to find the best solution to a problem without investing too much time and resources in a single solution.</p>
<h2 id="12-do-not-generate-blindly-or-to-much-complexity-at-once"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#12-do-not-generate-blindly-or-to-much-complexity-at-once">12 Do not generate blindly or to much complexity at once</a></h2><p>Break down complex tasks into smaller, manageable tasks for the AI. Instead of asking the AI to generate the complete project or component at once, break it down into smaller tasks, such as generating individual functions or classes. This will help you to maintain control over the code and it&rsquo;s logic.</p>
<p>You have to check each component or module for its adherence to the specifications and requirements.<br>
If you have lost the overview of the complexity and inner workings of the code, you have lost control over your code and must restart from a state where you were in control of your code.</p>
]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><h2 id="1-establish-a-clear-vision"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#1-establish-a-clear-vision">1 Establish a Clear Vision</a></h2><p>You are a human, you know how this world behaves, how your team and colleagues behave, and what your users expect. You have experienced the world, and you want to work together with a system that has no experience in this world you live in. Every decision in your project that you don&rsquo;t take and document will be taken for you by the AI.</p>
<p>Your responsibility of delivering quality code cannot be met if not even you know where long-lasting and difficult-to-change decisions are taken.<br>
You must know what parts of your code need to be thought through and what must be vigorously tested.</p>
<p>Think about and discuss the architecture, interfaces, data structures, and algorithms you want to use.
Think about how to test and validate your code to these specifications.</p>
<h2 id="2-maintain-precise-documentation"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#2-maintain-precise-documentation">2 Maintain Precise documentation</a></h2><p>You need to communicate to the AI in detail what you want to achieve, otherwise it will result in code that is unusable for your purpose.</p>
<p>Other developers also need to communicate this information to the AI. That makes it efficient to write as much documentation as practical in a standardized format and into the code repository itself.</p>
<p>Document the requirements, specifications, constraints, and architecture of your project in detail.<br>
Document your coding standards, best practices, and design patterns.<br>
Use flowcharts, UML diagrams, and other visual aids to communicate complex structures and workflows.<br>
Write pseudocode for complex algorithms and logic to guide the AI in understanding your intentions.</p>
<h2 id="3-build-debug-systems-that-aid-the-ai"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#3-build-debug-systems-that-aid-the-ai">3 Build debug systems that aid the AI</a></h2><p>Develop efficient debug systems for the AI to use, reducing the need for multiple expensive CLI commands or browsers to verify code functionality. This will save time and resources while simplifying the process for the AI to identify and resolve code issues.</p>
<p>For example: Build a system that collects logs from all nodes in a distributed system and provides abstracted information like &ldquo;The Data was send to all nodes&rdquo;, &ldquo;The Data X is saved on Node 1 but not on Node 2&rdquo;.</p>
<h2 id="4-mark-code-review-levels"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#4-mark-code-review-levels">4 Mark code review levels</a></h2><p>Not all code is equally important. Some parts of your codebase are critical and need to be reviewed with extra care. Other parts are less important and can be generated with less oversight.</p>
<p>Use a system that allows you to mark how thoroughly each function has been reviewed.</p>
<p>For example you can use a prompt that will let the AI put the comment <code>//A</code> behind functions it wrote to indicate that the function has been written by an AI and is not yet reviewed by a human.</p>
<h2 id="5-write-high-level-specifications-and-test-by-yourself"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#5-write-high-level-specifications-and-test-by-yourself">5 Write high level specifications and test by yourself</a></h2><p>AIs will cheat and use shortcuts eventually. They will write mocks, stubs, and hard coded values to make the code tests succeed while the code itself is not working and most of the time dangerous. Often AIs will adapt or outright delete test code to let the code pass tests.</p>
<p>You must discourage this behavior by writing property based high level specification tests yourself. Build them in a way that makes it hard for the AI to cheat without having big code segments dedicated to it.<br>
For example, use property based testing, restart the server and check in between if the database has the correct values.</p>
<p>Separate these test so the AI cannot edit them and prompt the AI not to change them.</p>
<h2 id="6-write-interface-tests-in-a-separate-context"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#6-write-interface-tests-in-a-separate-context">6 Write interface tests in a separate context</a></h2><p>Let an AI write property based interface tests for the expected behavior with as little context of the rest of the code as possible.<br>
This will generate tests that are uninfluenced by the &ldquo;implementation AI&rdquo; which will prevent the tests from being adapted to the implementation in a way that makes them useless or less effective.</p>
<p>Separate these tests so the AI cannot edit them without approval and prompt the AI not to change them.</p>
<h2 id="7-use-strict-linting-and-formatting-rules"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#7-use-strict-linting-and-formatting-rules">7 Use strict linting and formatting rules</a></h2><p>Use strict linting and formatting rules to ensure code quality and consistency. This will help you and your AI to find issues early.</p>
<h2 id="8-use-context-specific-coding-agent-prompts"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#8-use-context-specific-coding-agent-prompts">8 Use context specific coding agent prompts</a></h2><p>Save time and money by utilizing path specific coding agent prompts like <a href="https://www.anthropic.com/engineering/claude-code-best-practices#:~:text=Create%20CLAUDE.md%20files">CLAUDE.md</a>.</p>
<p>You can generate them automatically which will give your AI information it would otherwise as to create from scratch every time.</p>
<p>Try to provide as much high level information as practical, such as coding standards, best practices, design patterns, and specific requirements for the project. This will help the AI to generate code that is more aligned with your expectations and will reduce lookup time and cost.</p>
<h2 id="9-find-and-mark-functions-that-have-a-high-security-risk"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#9-find-and-mark-functions-that-have-a-high-security-risk">9 Find and mark functions that have a high security risk</a></h2><p>Identify and mark functions that have a high security risk, such as authentication, authorization, and data handling. These functions should be reviewed and tested with extra care and in such a way that a human has comprehended the logic of the function in all its dimensions and is confident about its correctness and safety.</p>
<p>Make this explicit with a comment like <code>//HIGH-RISK-UNREVIEWED</code> and <code>//HIGH-RISK-REVIEWED</code> to make sure that other developers are aware of the importance of these functions and will review them with extra care.</p>
<p>Make sure that the AI is instructed to change the review state of these functions as soon as it changes a single character in the function.<br>
Developers must make sure that the status of these functions is always correct.</p>
<h2 id="10-reduce-code-complexity-where-possible"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#10-reduce-code-complexity-where-possible">10 Reduce code complexity where possible</a></h2><p>Aim to reduce the complexity of the generated code where possible. Each single line of code will eat up your context window and make it harder for the AI and You to keep track of the overall logic of your code.<br>
Each avoidable line of code is costing energy, money and probability of future unsuccessful AI tasks.</p>
<h2 id="11-explore-problems-with-experiments-and-prototypes"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#11-explore-problems-with-experiments-and-prototypes">11 Explore problems with experiments and prototypes</a></h2><p>AI written code is cheap, use this to your advantage by exploring different solutions to a problem with experiments and prototypes with minimal specifications. This will allow you to find the best solution to a problem without investing too much time and resources in a single solution.</p>
<h2 id="12-do-not-generate-blindly-or-to-much-complexity-at-once"><a href="https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/#12-do-not-generate-blindly-or-to-much-complexity-at-once">12 Do not generate blindly or to much complexity at once</a></h2><p>Break down complex tasks into smaller, manageable tasks for the AI. Instead of asking the AI to generate the complete project or component at once, break it down into smaller tasks, such as generating individual functions or classes. This will help you to maintain control over the code and it&rsquo;s logic.</p>
<p>You have to check each component or module for its adherence to the specifications and requirements.<br>
If you have lost the overview of the complexity and inner workings of the code, you have lost control over your code and must restart from a state where you were in control of your code.</p>
]]></content:encoded></item><item><title>Releasing: GoQueueBench</title><link>https://heidenstedt.org/posts/2025/releasing-goqueuebench/</link><pubDate>Tue, 25 Mar 2025 15:44:38 +0000</pubDate><guid>https://heidenstedt.org/posts/2025/releasing-goqueuebench/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2025/releasing-goqueuebench/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>As i coded on <a href="https://github.com/i5heu/ouroboros-db">OuroborosDB</a> i noticed that i need a very fast queue for a rather unique architectural design decision.<br>
I try to build the network module in such a way that i can test the behavior completely deterministic while &ldquo;simulating&rdquo; entire clusters in a single process.</p>
<p>So i build a test prototype of my global network queue with go&rsquo;s channels and noticed that it was a major performance bottleneck, after writing 2 different ring buffer queue implementations it became clear that some queues behave completely different under different congestion levels and core counts - some so unpredictable that i just did not wanted to use them in my project.</p>
<p>This prompted me to take a relatively large chunk out of my free time and write a suite to benchmark different queue implementations i build under different conditions and score them based on their performance and predictability.</p>
<p>The result of this work is <a href="https://github.com/i5heu/GoQueueBench">GoQueueBench</a></p>
<p>These are the results of the benchmark suite:</p>
<table>
	<thead>
			<tr>
					<th>Implementation</th>
					<th>Overall Score</th>
					<th>Throughput Light Load</th>
					<th>Throughput Heavy Load</th>
					<th>Throughput Average</th>
					<th>Stability Ratio</th>
					<th>Homogeneity Factor</th>
					<th>Uncertainty</th>
					<th>Total Tests</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>VortexQueue</td>
					<td><strong>11341466</strong></td>
					<td>6926449</td>
					<td><strong>5502925</strong></td>
					<td><strong>8776309</strong></td>
					<td><strong>1.15</strong></td>
					<td>0.87</td>
					<td><strong>0.25</strong></td>
					<td>681</td>
			</tr>
			<tr>
					<td>LightningQueue</td>
					<td>9631771</td>
					<td>6638213</td>
					<td>4627690</td>
					<td>6036728</td>
					<td>0.99</td>
					<td><strong>0.95</strong></td>
					<td>0.31</td>
					<td>681</td>
			</tr>
			<tr>
					<td>FastMPMCQueue</td>
					<td>9384067</td>
					<td>6870924</td>
					<td>4598620</td>
					<td>6070151</td>
					<td>0.96</td>
					<td>0.93</td>
					<td>0.28</td>
					<td>681</td>
			</tr>
			<tr>
					<td>OptimizedMPMCQueue</td>
					<td>9105262</td>
					<td>6436385</td>
					<td>4379823</td>
					<td>5838555</td>
					<td>0.97</td>
					<td>0.94</td>
					<td>0.32</td>
					<td>681</td>
			</tr>
			<tr>
					<td>OptimizedMPMCQueueSharded</td>
					<td>8130197</td>
					<td>6369891</td>
					<td>3834140</td>
					<td>6781865</td>
					<td>0.84</td>
					<td>0.88</td>
					<td>0.39</td>
					<td>681</td>
			</tr>
			<tr>
					<td>MultiHeadQueue</td>
					<td>7391203</td>
					<td>4363332</td>
					<td>3492068</td>
					<td>5558849</td>
					<td>1.12</td>
					<td>0.91</td>
					<td>0.36</td>
					<td>681</td>
			</tr>
			<tr>
					<td>BasicMPMCQueue</td>
					<td>5599252</td>
					<td>4370889</td>
					<td>2669612</td>
					<td>3667715</td>
					<td>0.89</td>
					<td>0.93</td>
					<td>0.30</td>
					<td>681</td>
			</tr>
			<tr>
					<td>Golang Buffered Channel</td>
					<td>5312485</td>
					<td>6667828</td>
					<td>2760985</td>
					<td>4312720</td>
					<td>0.54</td>
					<td>0.82</td>
					<td>0.66</td>
					<td>681</td>
			</tr>
			<tr>
					<td>FastMPMCQueueTicket</td>
					<td>3229780</td>
					<td><strong>7705164</strong></td>
					<td>1203924</td>
					<td>5803821</td>
					<td>0.21</td>
					<td>0.64</td>
					<td>1.19</td>
					<td>681</td>
			</tr>
	</tbody>
</table>
<p>Please note that i build the package so that all queue adhere to the same interface and can be swapped out easily.</p>
]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2025/releasing-goqueuebench/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>As i coded on <a href="https://github.com/i5heu/ouroboros-db">OuroborosDB</a> i noticed that i need a very fast queue for a rather unique architectural design decision.<br>
I try to build the network module in such a way that i can test the behavior completely deterministic while &ldquo;simulating&rdquo; entire clusters in a single process.</p>
<p>So i build a test prototype of my global network queue with go&rsquo;s channels and noticed that it was a major performance bottleneck, after writing 2 different ring buffer queue implementations it became clear that some queues behave completely different under different congestion levels and core counts - some so unpredictable that i just did not wanted to use them in my project.</p>
<p>This prompted me to take a relatively large chunk out of my free time and write a suite to benchmark different queue implementations i build under different conditions and score them based on their performance and predictability.</p>
<p>The result of this work is <a href="https://github.com/i5heu/GoQueueBench">GoQueueBench</a></p>
<p>These are the results of the benchmark suite:</p>
<table>
	<thead>
			<tr>
					<th>Implementation</th>
					<th>Overall Score</th>
					<th>Throughput Light Load</th>
					<th>Throughput Heavy Load</th>
					<th>Throughput Average</th>
					<th>Stability Ratio</th>
					<th>Homogeneity Factor</th>
					<th>Uncertainty</th>
					<th>Total Tests</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>VortexQueue</td>
					<td><strong>11341466</strong></td>
					<td>6926449</td>
					<td><strong>5502925</strong></td>
					<td><strong>8776309</strong></td>
					<td><strong>1.15</strong></td>
					<td>0.87</td>
					<td><strong>0.25</strong></td>
					<td>681</td>
			</tr>
			<tr>
					<td>LightningQueue</td>
					<td>9631771</td>
					<td>6638213</td>
					<td>4627690</td>
					<td>6036728</td>
					<td>0.99</td>
					<td><strong>0.95</strong></td>
					<td>0.31</td>
					<td>681</td>
			</tr>
			<tr>
					<td>FastMPMCQueue</td>
					<td>9384067</td>
					<td>6870924</td>
					<td>4598620</td>
					<td>6070151</td>
					<td>0.96</td>
					<td>0.93</td>
					<td>0.28</td>
					<td>681</td>
			</tr>
			<tr>
					<td>OptimizedMPMCQueue</td>
					<td>9105262</td>
					<td>6436385</td>
					<td>4379823</td>
					<td>5838555</td>
					<td>0.97</td>
					<td>0.94</td>
					<td>0.32</td>
					<td>681</td>
			</tr>
			<tr>
					<td>OptimizedMPMCQueueSharded</td>
					<td>8130197</td>
					<td>6369891</td>
					<td>3834140</td>
					<td>6781865</td>
					<td>0.84</td>
					<td>0.88</td>
					<td>0.39</td>
					<td>681</td>
			</tr>
			<tr>
					<td>MultiHeadQueue</td>
					<td>7391203</td>
					<td>4363332</td>
					<td>3492068</td>
					<td>5558849</td>
					<td>1.12</td>
					<td>0.91</td>
					<td>0.36</td>
					<td>681</td>
			</tr>
			<tr>
					<td>BasicMPMCQueue</td>
					<td>5599252</td>
					<td>4370889</td>
					<td>2669612</td>
					<td>3667715</td>
					<td>0.89</td>
					<td>0.93</td>
					<td>0.30</td>
					<td>681</td>
			</tr>
			<tr>
					<td>Golang Buffered Channel</td>
					<td>5312485</td>
					<td>6667828</td>
					<td>2760985</td>
					<td>4312720</td>
					<td>0.54</td>
					<td>0.82</td>
					<td>0.66</td>
					<td>681</td>
			</tr>
			<tr>
					<td>FastMPMCQueueTicket</td>
					<td>3229780</td>
					<td><strong>7705164</strong></td>
					<td>1203924</td>
					<td>5803821</td>
					<td>0.21</td>
					<td>0.64</td>
					<td>1.19</td>
					<td>681</td>
			</tr>
	</tbody>
</table>
<p>Please note that i build the package so that all queue adhere to the same interface and can be swapped out easily.</p>
]]></content:encoded></item><item><title>Constraints in Go</title><link>https://heidenstedt.org/links/constraints-in-go/</link><pubDate>Sun, 17 Nov 2024 20:44:42 +0000</pubDate><guid>https://heidenstedt.org/links/constraints-in-go/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/links/constraints-in-go/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>I want to share this great article about generic coding in Go:  <a href="https://bitfieldconsulting.com/posts/constraints">https://bitfieldconsulting.com/posts/constraints</a></p>
<p>Also <a href="https://go-proverbs.github.io/">Go Proverbs</a> is quite nice!</p>
<p>Ohh and this Blog has now footnotes and popups for footnotes! <sup id="fnref:1"><a href="https://heidenstedt.org/links/constraints-in-go/#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<h2 id="summary-generated"><a href="https://heidenstedt.org/links/constraints-in-go/#summary-generated">Summary (Generated):</a></h2><p>In this tutorial, John Arundel explores constraints in Go, the paradoxical feature of generics that simultaneously limits and expands possibilities. By delving into method sets, type elements, unions, intersections, and approximations, he demonstrates how constraints enable precise operations on type parameters. Whether you&rsquo;re learning to leverage <code>fmt.Stringer</code>, creating flexible numeric constraints, or handling derived types, this guide unlocks a deeper understanding of Go&rsquo;s generics—perfect for honing your skills or tackling practical challenges in coding.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This is a footnote!<br>
And this works even with multiple lines.<br>
And <code>code</code> too!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;Hello, World!&#39;</span>);
</span></span></code></pre></div>&#160;<a href="https://heidenstedt.org/links/constraints-in-go/#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></li>
</ol>
</div>
]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/links/constraints-in-go/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>I want to share this great article about generic coding in Go:  <a href="https://bitfieldconsulting.com/posts/constraints">https://bitfieldconsulting.com/posts/constraints</a></p>
<p>Also <a href="https://go-proverbs.github.io/">Go Proverbs</a> is quite nice!</p>
<p>Ohh and this Blog has now footnotes and popups for footnotes! <sup id="fnref:1"><a href="https://heidenstedt.org/links/constraints-in-go/#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<h2 id="summary-generated"><a href="https://heidenstedt.org/links/constraints-in-go/#summary-generated">Summary (Generated):</a></h2><p>In this tutorial, John Arundel explores constraints in Go, the paradoxical feature of generics that simultaneously limits and expands possibilities. By delving into method sets, type elements, unions, intersections, and approximations, he demonstrates how constraints enable precise operations on type parameters. Whether you&rsquo;re learning to leverage <code>fmt.Stringer</code>, creating flexible numeric constraints, or handling derived types, this guide unlocks a deeper understanding of Go&rsquo;s generics—perfect for honing your skills or tackling practical challenges in coding.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>This is a footnote!<br>
And this works even with multiple lines.<br>
And <code>code</code> too!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;Hello, World!&#39;</span>);
</span></span></code></pre></div>&#160;<a href="https://heidenstedt.org/links/constraints-in-go/#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></li>
</ol>
</div>
]]></content:encoded></item><item><title>Release: OuroborosDB Data Storage Calculator</title><link>https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/</link><pubDate>Fri, 01 Nov 2024 11:17:10 +0200</pubDate><guid>https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>I forgot to mention that i released a new tool for my project <a href="https://github.com/i5heu/ouroboros-db">ouroboros-db</a>, so here it is:</p>
<p>The &ldquo;OuroborosDB Overhead Calculator&rdquo; is a little tool which helps you to calculate the overhead of erasure coding systems while also considering the overhead of indexes and the blocks themselves. It is kinda fun to play around with so give it a try!</p>
<p><a href="https://i5heu.github.io/ouroboros-db-overhead-calculator/">https://i5heu.github.io/ouroboros-db-overhead-calculator/</a></p>
<video width="100%" controls>
  <source src="https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/demo.webm" type="video/webm">
  Your browser does not support the video tag.
</video>]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>I forgot to mention that i released a new tool for my project <a href="https://github.com/i5heu/ouroboros-db">ouroboros-db</a>, so here it is:</p>
<p>The &ldquo;OuroborosDB Overhead Calculator&rdquo; is a little tool which helps you to calculate the overhead of erasure coding systems while also considering the overhead of indexes and the blocks themselves. It is kinda fun to play around with so give it a try!</p>
<p><a href="https://i5heu.github.io/ouroboros-db-overhead-calculator/">https://i5heu.github.io/ouroboros-db-overhead-calculator/</a></p>
<video width="100%" controls>
  <source src="https://heidenstedt.org/posts/2024/release-ouroborosdb-data-storage-calculator/demo.webm" type="video/webm">
  Your browser does not support the video tag.
</video>]]></content:encoded></item><item><title>Ouroboros DB Dev Journal: Erasure Coding</title><link>https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/</link><pubDate>Tue, 27 Aug 2024 17:55:05 +0200</pubDate><guid>https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>This is a Dev Journal for the Ouroboros DB Project.<br>
I try to write down my thoughts and ideas Somewhat structured to have it as a reference for later and i publish it to give this information a chance to help other and to get feedback from the community.<br>
If you have feedback you can write me on my <a href="https://mastodon.social/@heidenstedt">Mastodon</a>.</p>
<p>Pls note that this is only a Dev Journal and not a Blog Post, so it may be a bit unstructured and not as polished as a Blog Post, including typos and other errors.</p>
<h2 id="tldr"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#tldr">TL;DR:</a></h2><p>Today i worked on a refactoring of the architecture and feasibility of erasure coding for <a href="https://github.com/i5heu/ouroboros-db">Ouroboros DB</a>. There are some concerns i had regarding the potential index size and overhead that will result from it, and as it turns out, it is not as bad as i thought but i need a DHT for the index.</p>
<h2 id="architecture"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#architecture">Architecture</a></h2><p>I think it would be super handy to be able to run parts of data pipelines (eg. storing files into chunked,compressed, encrypted and then erasure coded blocks) in a distributed manner. for safety and because i want to be able to run trustless nodes that can&rsquo;t see the raw data, it would be necessary to have the file chunking, compression and encryption part on the server the client currently speaks too, although it would be possible to pre-chunk the file on the client and upload it to different nodes, although here is the question if it is easy to port the chunking algorithm to browser JS or WASM.</p>
<h3 id="modules"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#modules">Modules</a></h3><p>Refactoring of the code is needed to implement <code>erasure coding</code>, maybe we can even get rid of the <code>chunk</code> entirely as a stored thing since we have the data in the <code>parity block</code>s already.</p>
<p>Maybe best to add the <code>erasure coding</code> to the <code>StoreDataPipeline</code> and add the needed <code>erasure coding</code> metadata to <code>ChunkData</code>.</p>
<p>ASCII Art of the new architecture (click to get the .txt file):</p>
<a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/architecture.txt" target="_blank">
<p><div class="imageLoadingWrap"><img
          alt="ASCII Art of the new architecture"
          title="ASCII Art of the new architecture"
          loading="lazy"
          src="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_96d4787568ab57f9.webp"
          width="3030"
          height="871"
          srcset='/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_2cb9192ee549f6f7.avif 100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b05e3863fdd4ce9a.webp 100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_ab2ece513e436730.avif 200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b80b28c6ea927abb.webp 200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9a6a5eab6370057.avif 300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f8a619137d8295b3.webp 300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b9e944c8f507ee53.avif 400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9b1c897b51eca118.webp 400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_97dc6486f99e7f3c.avif 500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1048466be74d0ae7.webp 500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_12dba54ade38bf4a.avif 600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_4fb7e4485e6d9ba8.webp 600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_cc0d65b877a694cc.avif 700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_863c0c2a40d204e.webp 700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a0b76a1673bd8ce1.avif 800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_48b438099fcc934f.webp 800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5c003cfa191ab46a.avif 900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f03d0655d1a1a4da.webp 900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_42356eb882d4c7df.avif 1000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_ea45c55f65bd9414.webp 1000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a794c31c2c196144.avif 1100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f8ecf047dd3ef009.webp 1100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_797db1b158ee89ac.avif 1200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5900068a81c61786.webp 1200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_aba964185e50c26.avif 1300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b9393aa6e5960f12.webp 1300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_311d76129c9977b3.avif 1400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_50cf36bdf8cc20a4.webp 1400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_35fb69dfc8065d4d.avif 1500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d03d70c6373baf8d.webp 1500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f793111d3415434c.avif 1600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_50de16a06f6c909.webp 1600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f44d13cbf9438f06.avif 1700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a01af93ff7648eb3.webp 1700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1c062ad7c62ae03a.avif 1800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9fa6b205fb52c14d.webp 1800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_e28bcab6f174e919.avif 1900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_2eb74c1265d3c7b0.webp 1900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_54f2d99662709774.avif 2000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1e31b1da25e1eb32.webp 2000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_646abb2a2bff3fa3.avif 2100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f089d367a3a280fc.webp 2100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1978db329ec16d6d.avif 2200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_6ee5a59dc7098578.webp 2200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_7e06f488ab5ffa79.avif 2300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_3e2c0136633d8f0.webp 2300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_8e267fbf50cb3a52.avif 2400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5fa6ff521302409f.webp 2400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d1ab2af2aaec0825.avif 2500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_7fb22e5fa281cb76.webp 2500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_4569bdffbcc0329b.avif 2600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_c30c96df17374589.webp 2600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_aa217e5aa81c2f2c.avif 2700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a6644da4d424ff65.webp 2700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d128f208c0c6ba4.avif 2800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_bd4e57588a16519a.webp 2800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_6b01e3577982cafa.avif 2900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_c5dbd5148973c5ad.webp 2900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5d1962d1966460a.avif 3000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_3abd1e7ef89d2c43.webp 3000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_e80e0bc829f354e7.avif 3030w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_80249ad413f32588.webp 3030w
          '
          sizes="(max-width: 672px) calc(85vw - 32px), (max-width: 736px) 640px, 657px"
        ><div class="imageLoading"></div>
</div></p>
</a>
<h2 id="erasure-coding"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#erasure-coding">Erasure Coding</a></h2><p>For now i think it is okay yo make the erasure coding a simple n6 k3, which would result in a <code>parity block</code> size of 327,680 Bytes or 0.31MB as average. This would result in about 1.875MB per chunk that is 1.25MB big in average. This would result in a 50% overhead for the erasure coding, which i think is quite okay.</p>
<p>For the goal of storing 100TB in it, which are about 400M Chunks, we would need 2,400,000,000 <code>parity block</code>s, aka 2,4 Billion.</p>
<p>If we consider following overhead for the erasure coding:</p>
<details>
  <summary>Parity Meta Data</summary>
    This is the Meta Data for a `parity block`:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;parityHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;chunkHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;sizeByte&#34;</span>: <span style="color:#ae81ff">433000</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;lastChecked&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;reblanceLog&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>],
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;userLog&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>],
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;this is for the KV Key&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></details>
<p>We see that <code>parity block metadata</code> has under 2373 Bytes of overhead, which is about 0.72%% of the <code>parity block</code> size (very good). If one node would need to store the entire hash table we look at a size of 5.18TB, which means that we need a DHT for this to work. This also is the case for the Events, which introduce more storage overhead (more in <a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#dht">DHT</a> )</p>
<h3 id="dht"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#dht">DHT</a></h3><p>We need additional DHT Metadata like this:</p>
<details>
  <summary>DHT Meta Data</summary>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;parityHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;storingNodes&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></details>
<p>This example meta data has a size of 674 Bytes, which is about 0.21% of the <code>parity block</code> size. The <code>DHT meta data</code> would require an additional 1.47TB of storage.</p>
<h3 id="overhead"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#overhead">Overhead</a></h3><p><code>DHT meta data</code> in combination with the <code>parity block meta data</code> would have a total overhead of 0.93%% of the <code>erasure coding metadata</code> relative to the <code>erasure coding parity block size</code>, the entire metadata overhead at 100TB and 2,4 Billion <code>parity block</code>s would be 6.65TB.</p>
<p>Adding this to the overhead from the <code>erasure coding</code> which are 50% we would have a total overhead of 56.65% relative to the raw data size. If we have a utilization of each <code>chunk</code> of 1310720 Bits which has been achieved with 10MB files with random binary data. This would result in a HDD to raw data ratio of 43.35% (which is pretty good for a k6n3 config and having self healing capabilities) for following configuration:</p>
<ul>
<li>100TB of raw data</li>
<li>data deduplication via BuzzHash into chunks</li>
<li>chunk compression via Zstd</li>
<li>chunk encryption via AES256</li>
<li>each chunk becomes 6 parity blocks of which 3 can be lost without data loss</li>
</ul>
<h2 id="conclusion"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#conclusion">Conclusion</a></h2><p>I have written a Google Calc Spreadsheet for it, which you can find here: <a href="https://docs.google.com/spreadsheets/d/12Ad4vvA0dLSOffDLz6gMkkIJkYNZE70gY0wI1Qqkg8c/edit?usp=sharing">ouroboros-db Overhead Calculator</a>.</p>
<p>Though this Spreadsheet is neat, i discoverd that i need some surface plotting to find the best configuration for the erasure coding.<br>
Sadly there is no way to do this in Google Calc, so i will need to write a small Browser App for it&hellip; maybe i use Svelte for it, i haven&rsquo;t used it in a while now.</p>
<h2 id="further-reading"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#further-reading">Further Reading</a></h2><p>A good overview over what erasure coding is about: <a href="https://transactional.blog/blog/2024-erasure-coding">Erasure Coding for Distributed Systems</a><br>
Also See <a href="https://news.ycombinator.com/item?id=41361281">HN comments</a></p>
]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>This is a Dev Journal for the Ouroboros DB Project.<br>
I try to write down my thoughts and ideas Somewhat structured to have it as a reference for later and i publish it to give this information a chance to help other and to get feedback from the community.<br>
If you have feedback you can write me on my <a href="https://mastodon.social/@heidenstedt">Mastodon</a>.</p>
<p>Pls note that this is only a Dev Journal and not a Blog Post, so it may be a bit unstructured and not as polished as a Blog Post, including typos and other errors.</p>
<h2 id="tldr"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#tldr">TL;DR:</a></h2><p>Today i worked on a refactoring of the architecture and feasibility of erasure coding for <a href="https://github.com/i5heu/ouroboros-db">Ouroboros DB</a>. There are some concerns i had regarding the potential index size and overhead that will result from it, and as it turns out, it is not as bad as i thought but i need a DHT for the index.</p>
<h2 id="architecture"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#architecture">Architecture</a></h2><p>I think it would be super handy to be able to run parts of data pipelines (eg. storing files into chunked,compressed, encrypted and then erasure coded blocks) in a distributed manner. for safety and because i want to be able to run trustless nodes that can&rsquo;t see the raw data, it would be necessary to have the file chunking, compression and encryption part on the server the client currently speaks too, although it would be possible to pre-chunk the file on the client and upload it to different nodes, although here is the question if it is easy to port the chunking algorithm to browser JS or WASM.</p>
<h3 id="modules"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#modules">Modules</a></h3><p>Refactoring of the code is needed to implement <code>erasure coding</code>, maybe we can even get rid of the <code>chunk</code> entirely as a stored thing since we have the data in the <code>parity block</code>s already.</p>
<p>Maybe best to add the <code>erasure coding</code> to the <code>StoreDataPipeline</code> and add the needed <code>erasure coding</code> metadata to <code>ChunkData</code>.</p>
<p>ASCII Art of the new architecture (click to get the .txt file):</p>
<a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/architecture.txt" target="_blank">
<p><div class="imageLoadingWrap"><img
          alt="ASCII Art of the new architecture"
          title="ASCII Art of the new architecture"
          loading="lazy"
          src="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_96d4787568ab57f9.webp"
          width="3030"
          height="871"
          srcset='/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_2cb9192ee549f6f7.avif 100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b05e3863fdd4ce9a.webp 100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_ab2ece513e436730.avif 200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b80b28c6ea927abb.webp 200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9a6a5eab6370057.avif 300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f8a619137d8295b3.webp 300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b9e944c8f507ee53.avif 400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9b1c897b51eca118.webp 400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_97dc6486f99e7f3c.avif 500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1048466be74d0ae7.webp 500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_12dba54ade38bf4a.avif 600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_4fb7e4485e6d9ba8.webp 600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_cc0d65b877a694cc.avif 700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_863c0c2a40d204e.webp 700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a0b76a1673bd8ce1.avif 800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_48b438099fcc934f.webp 800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5c003cfa191ab46a.avif 900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f03d0655d1a1a4da.webp 900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_42356eb882d4c7df.avif 1000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_ea45c55f65bd9414.webp 1000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a794c31c2c196144.avif 1100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f8ecf047dd3ef009.webp 1100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_797db1b158ee89ac.avif 1200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5900068a81c61786.webp 1200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_aba964185e50c26.avif 1300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_b9393aa6e5960f12.webp 1300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_311d76129c9977b3.avif 1400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_50cf36bdf8cc20a4.webp 1400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_35fb69dfc8065d4d.avif 1500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d03d70c6373baf8d.webp 1500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f793111d3415434c.avif 1600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_50de16a06f6c909.webp 1600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f44d13cbf9438f06.avif 1700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a01af93ff7648eb3.webp 1700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1c062ad7c62ae03a.avif 1800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_9fa6b205fb52c14d.webp 1800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_e28bcab6f174e919.avif 1900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_2eb74c1265d3c7b0.webp 1900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_54f2d99662709774.avif 2000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1e31b1da25e1eb32.webp 2000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_646abb2a2bff3fa3.avif 2100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_f089d367a3a280fc.webp 2100w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_1978db329ec16d6d.avif 2200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_6ee5a59dc7098578.webp 2200w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_7e06f488ab5ffa79.avif 2300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_3e2c0136633d8f0.webp 2300w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_8e267fbf50cb3a52.avif 2400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5fa6ff521302409f.webp 2400w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d1ab2af2aaec0825.avif 2500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_7fb22e5fa281cb76.webp 2500w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_4569bdffbcc0329b.avif 2600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_c30c96df17374589.webp 2600w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_aa217e5aa81c2f2c.avif 2700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_a6644da4d424ff65.webp 2700w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_d128f208c0c6ba4.avif 2800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_bd4e57588a16519a.webp 2800w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_6b01e3577982cafa.avif 2900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_c5dbd5148973c5ad.webp 2900w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_5d1962d1966460a.avif 3000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_3abd1e7ef89d2c43.webp 3000w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_e80e0bc829f354e7.avif 3030w,/posts/2024/ouroboros-db-dev-journal-erasure-coding/Architecture_hu_80249ad413f32588.webp 3030w
          '
          sizes="(max-width: 672px) calc(85vw - 32px), (max-width: 736px) 640px, 657px"
        ><div class="imageLoading"></div>
</div></p>
</a>
<h2 id="erasure-coding"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#erasure-coding">Erasure Coding</a></h2><p>For now i think it is okay yo make the erasure coding a simple n6 k3, which would result in a <code>parity block</code> size of 327,680 Bytes or 0.31MB as average. This would result in about 1.875MB per chunk that is 1.25MB big in average. This would result in a 50% overhead for the erasure coding, which i think is quite okay.</p>
<p>For the goal of storing 100TB in it, which are about 400M Chunks, we would need 2,400,000,000 <code>parity block</code>s, aka 2,4 Billion.</p>
<p>If we consider following overhead for the erasure coding:</p>
<details>
  <summary>Parity Meta Data</summary>
    This is the Meta Data for a `parity block`:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;parityHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;chunkHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;sizeByte&#34;</span>: <span style="color:#ae81ff">433000</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;lastChecked&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;reblanceLog&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>],
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;userLog&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;time&#34;</span>: <span style="color:#ae81ff">1724760126282</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;from&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>],
</span></span><span style="display:flex;"><span><span style="color:#f92672">&#34;this is for the KV Key&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></details>
<p>We see that <code>parity block metadata</code> has under 2373 Bytes of overhead, which is about 0.72%% of the <code>parity block</code> size (very good). If one node would need to store the entire hash table we look at a size of 5.18TB, which means that we need a DHT for this to work. This also is the case for the Events, which introduce more storage overhead (more in <a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#dht">DHT</a> )</p>
<h3 id="dht"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#dht">DHT</a></h3><p>We need additional DHT Metadata like this:</p>
<details>
  <summary>DHT Meta Data</summary>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;parityHash&#34;</span>: <span style="color:#e6db74">&#34;aeae379a6e857728e44164267fdb7a0e27b205d757cc19899586c89dbb221930f1813d02ff93a661859bc17065eac4d6edf3c38a034e6283a84754d52917e5b0&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;storingNodes&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;node&#34;</span>: <span style="color:#e6db74">&#34;2deb000b57bfac9d72c14d4ed967b572&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;lastValidated&#34;</span>: <span style="color:#ae81ff">1724760126282</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></details>
<p>This example meta data has a size of 674 Bytes, which is about 0.21% of the <code>parity block</code> size. The <code>DHT meta data</code> would require an additional 1.47TB of storage.</p>
<h3 id="overhead"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#overhead">Overhead</a></h3><p><code>DHT meta data</code> in combination with the <code>parity block meta data</code> would have a total overhead of 0.93%% of the <code>erasure coding metadata</code> relative to the <code>erasure coding parity block size</code>, the entire metadata overhead at 100TB and 2,4 Billion <code>parity block</code>s would be 6.65TB.</p>
<p>Adding this to the overhead from the <code>erasure coding</code> which are 50% we would have a total overhead of 56.65% relative to the raw data size. If we have a utilization of each <code>chunk</code> of 1310720 Bits which has been achieved with 10MB files with random binary data. This would result in a HDD to raw data ratio of 43.35% (which is pretty good for a k6n3 config and having self healing capabilities) for following configuration:</p>
<ul>
<li>100TB of raw data</li>
<li>data deduplication via BuzzHash into chunks</li>
<li>chunk compression via Zstd</li>
<li>chunk encryption via AES256</li>
<li>each chunk becomes 6 parity blocks of which 3 can be lost without data loss</li>
</ul>
<h2 id="conclusion"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#conclusion">Conclusion</a></h2><p>I have written a Google Calc Spreadsheet for it, which you can find here: <a href="https://docs.google.com/spreadsheets/d/12Ad4vvA0dLSOffDLz6gMkkIJkYNZE70gY0wI1Qqkg8c/edit?usp=sharing">ouroboros-db Overhead Calculator</a>.</p>
<p>Though this Spreadsheet is neat, i discoverd that i need some surface plotting to find the best configuration for the erasure coding.<br>
Sadly there is no way to do this in Google Calc, so i will need to write a small Browser App for it&hellip; maybe i use Svelte for it, i haven&rsquo;t used it in a while now.</p>
<h2 id="further-reading"><a href="https://heidenstedt.org/posts/2024/ouroboros-db-dev-journal-erasure-coding/#further-reading">Further Reading</a></h2><p>A good overview over what erasure coding is about: <a href="https://transactional.blog/blog/2024-erasure-coding">Erasure Coding for Distributed Systems</a><br>
Also See <a href="https://news.ycombinator.com/item?id=41361281">HN comments</a></p>
]]></content:encoded></item><item><title>My New Public Service: PathfinderBeacon</title><link>https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/</link><pubDate>Fri, 23 Aug 2024 16:00:00 +0200</pubDate><guid>https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/</guid><description><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>In the midst of working on my project, <a href="https://github.com/i5heu/ouroboros-db">ouroboros-db</a>, I realized I needed a straightforward way to locate other nodes using the same RSA key. That&rsquo;s when <a href="https://github.com/i5heu/PathfinderBeacon">PathfinderBeacon</a> came into being and that i release to the public with these words.</p>
<h2 id="what-is-pathfinderbeacon"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#what-is-pathfinderbeacon">What is PathfinderBeacon?</a></h2><p><a href="https://github.com/i5heu/PathfinderBeacon">PathfinderBeacon</a> is a tool designed to make it easier to bootstrap your distributed systems using just a RSA key and one of the most robust dictionaries available: DNS. Since DNS inherently caches information at various levels, it allows PathfinderBeacon to deliver node addresses quickly and with minimal bandwidth usage. This means if multiple searches are conducted within the same network for the same room, there&rsquo;s a high chance the requests won&rsquo;t even leave your local network, thanks to the caching capabilities of your router&rsquo;s local DNS.</p>
<p>You can think of it like a DDNS (Dynamic Domain Name System) service, but you only need an RSA key to write to a subdomain. The subdomain is generated from the RSA key, and there is little surface for abuse since you can only publish highly sanitized TXT records.</p>
<h2 id="how-it-works"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#how-it-works">How It Works</a></h2><p>Setting up is pretty simple. You either provide an RSA key or let PathfinderBeacon generate one for you. Once set, you can publish your room and node addresses, and anyone with the same RSA key can write to the same room, while anyone can read from it. This makes it easy to bootstrap your distributed systems without the need of running your own bootstrap service.</p>
<p>Currently, there is an official Golang library for interacting with PathfinderBeacon, which you can find <a href="https://github.com/i5heu/PathfinderBeacon-Client-Go">here</a>. If you&rsquo;re interested in developing libraries for other programming languages, feel free to reach out, and I&rsquo;d be glad to assist and subsequently feature your work on the project repository.</p>
<h2 id="future-directions"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#future-directions">Future Directions</a></h2><p>For me this project is pretty much finished since it solves the underlying problem quite effectively, but i am fascinated by this problem and i would love to develop PathfinderBeacon further, maybe even in a distributed thingy without a central server, private rooms and much more is thinkable. You can checkout the <a href="https://github.com/i5heu/PathfinderBeacon?tab=readme-ov-file#potential-future-features-and-ideas">README</a> for more ideas.</p>
<p>So, that’s PathfinderBeacon in a nutshell—a simple, secure way to manage node addresses within distributed systems. It&rsquo;s a small project with big potential, and I&rsquo;m excited to see how it can support and simplify the management of distributed networks.</p>
<p>Thanks for reading, and I’m looking forward to constructive feedback or contributions!</p>
<p>You can find PathfinderBeacon on <a href="https://github.com/i5heu/PathfinderBeacon">GitHub</a></p>
]]></description><content:encoded><![CDATA[<p>
      <em>Best viewed on the <a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/">original page</a>, where extended functionality like the
    footnote helper is available.</em>
    </p><p>In the midst of working on my project, <a href="https://github.com/i5heu/ouroboros-db">ouroboros-db</a>, I realized I needed a straightforward way to locate other nodes using the same RSA key. That&rsquo;s when <a href="https://github.com/i5heu/PathfinderBeacon">PathfinderBeacon</a> came into being and that i release to the public with these words.</p>
<h2 id="what-is-pathfinderbeacon"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#what-is-pathfinderbeacon">What is PathfinderBeacon?</a></h2><p><a href="https://github.com/i5heu/PathfinderBeacon">PathfinderBeacon</a> is a tool designed to make it easier to bootstrap your distributed systems using just a RSA key and one of the most robust dictionaries available: DNS. Since DNS inherently caches information at various levels, it allows PathfinderBeacon to deliver node addresses quickly and with minimal bandwidth usage. This means if multiple searches are conducted within the same network for the same room, there&rsquo;s a high chance the requests won&rsquo;t even leave your local network, thanks to the caching capabilities of your router&rsquo;s local DNS.</p>
<p>You can think of it like a DDNS (Dynamic Domain Name System) service, but you only need an RSA key to write to a subdomain. The subdomain is generated from the RSA key, and there is little surface for abuse since you can only publish highly sanitized TXT records.</p>
<h2 id="how-it-works"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#how-it-works">How It Works</a></h2><p>Setting up is pretty simple. You either provide an RSA key or let PathfinderBeacon generate one for you. Once set, you can publish your room and node addresses, and anyone with the same RSA key can write to the same room, while anyone can read from it. This makes it easy to bootstrap your distributed systems without the need of running your own bootstrap service.</p>
<p>Currently, there is an official Golang library for interacting with PathfinderBeacon, which you can find <a href="https://github.com/i5heu/PathfinderBeacon-Client-Go">here</a>. If you&rsquo;re interested in developing libraries for other programming languages, feel free to reach out, and I&rsquo;d be glad to assist and subsequently feature your work on the project repository.</p>
<h2 id="future-directions"><a href="https://heidenstedt.org/posts/2024/my-new-public-service-pathfinderbeacon/#future-directions">Future Directions</a></h2><p>For me this project is pretty much finished since it solves the underlying problem quite effectively, but i am fascinated by this problem and i would love to develop PathfinderBeacon further, maybe even in a distributed thingy without a central server, private rooms and much more is thinkable. You can checkout the <a href="https://github.com/i5heu/PathfinderBeacon?tab=readme-ov-file#potential-future-features-and-ideas">README</a> for more ideas.</p>
<p>So, that’s PathfinderBeacon in a nutshell—a simple, secure way to manage node addresses within distributed systems. It&rsquo;s a small project with big potential, and I&rsquo;m excited to see how it can support and simplify the management of distributed networks.</p>
<p>Thanks for reading, and I’m looking forward to constructive feedback or contributions!</p>
<p>You can find PathfinderBeacon on <a href="https://github.com/i5heu/PathfinderBeacon">GitHub</a></p>
]]></content:encoded></item></channel></rss>