<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: arhuman</title>
    <description>The latest articles on DEV Community by arhuman (@arhuman).</description>
    <link>https://dev.to/arhuman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F176648%2Fc3b6223f-393d-463a-90d8-6eefcf29a12b.jpeg</url>
      <title>DEV Community: arhuman</title>
      <link>https://dev.to/arhuman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arhuman"/>
    <language>en</language>
    <item>
      <title>I compressed timestamps before zstd and got up to 26.5% smaller log archives</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Sun, 17 May 2026 07:05:52 +0000</pubDate>
      <link>https://dev.to/arhuman/i-compressed-timestamps-before-zstd-and-got-up-to-265-smaller-log-archives-2i7b</link>
      <guid>https://dev.to/arhuman/i-compressed-timestamps-before-zstd-and-got-up-to-265-smaller-log-archives-2i7b</guid>
      <description>&lt;p&gt;This morning, I had fun compressing time.&lt;/p&gt;

&lt;p&gt;But before you picture me as a theoretical physics genius or a crackpot in need of a straitjacket, let me explain.&lt;/p&gt;

&lt;p&gt;I am currently working on &lt;a href="https://github.com/arhuman/metarc-go" rel="noopener noreferrer"&gt;Metarc&lt;/a&gt;, a &lt;code&gt;metacompression&lt;/code&gt; tool.&lt;/p&gt;

&lt;p&gt;By &lt;code&gt;metacompression&lt;/code&gt;, I mean: applying smart transformations to certain structures before handing the data to a classical compressor like &lt;code&gt;zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dates are a great playground for understanding this idea.&lt;/p&gt;

&lt;p&gt;They look like text, but they actually contain a very dense structure that can be exploited.&lt;/p&gt;

&lt;p&gt;And by exploiting this structure, &lt;code&gt;Metarc&lt;/code&gt; can achieve compression gains of up to &lt;strong&gt;26.5%&lt;/strong&gt; compared to &lt;code&gt;tar+zstd&lt;/code&gt; on some log datasets.&lt;/p&gt;

&lt;h2&gt;
  
  
  General-purpose compressors see bytes, not dates
&lt;/h2&gt;

&lt;p&gt;Consider this date: &lt;code&gt;2026-05-11 10:36:19&lt;/code&gt; That is 19 bytes of text.&lt;/p&gt;

&lt;p&gt;For a general-purpose compressor, this is not fundamentally a date. It is a sequence of characters.&lt;/p&gt;

&lt;p&gt;It can exploit pattern repetitions, but not the fact that this string represents a precise instant, with a known structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;year&lt;/li&gt;
&lt;li&gt;month&lt;/li&gt;
&lt;li&gt;day&lt;/li&gt;
&lt;li&gt;hour&lt;/li&gt;
&lt;li&gt;minute&lt;/li&gt;
&lt;li&gt;second&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This difference in perspective changes everything.&lt;/p&gt;

&lt;p&gt;Where a general-purpose compressor sees characters, &lt;code&gt;Metarc&lt;/code&gt; can recognize a structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an instant&lt;/li&gt;
&lt;li&gt;a format&lt;/li&gt;
&lt;li&gt;sometimes a timezone&lt;/li&gt;
&lt;li&gt;sometimes a precision in milliseconds or nanoseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the core idea.&lt;/p&gt;

&lt;p&gt;Compress the structure before compressing the bytes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logs are the obvious test ground
&lt;/h2&gt;

&lt;p&gt;To test this idea, log files were the obvious ground.&lt;/p&gt;

&lt;p&gt;They contain many dates, in various formats, with a very concrete constraint: you must be able to restore exactly the original text.&lt;/p&gt;

&lt;p&gt;Effectively compressing a date while keeping enough information to restore it in its original textual format imposes three constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;limit the complexity of detection and compression;&lt;/li&gt;
&lt;li&gt;minimize the size of format metadata;&lt;/li&gt;
&lt;li&gt;compress the most frequent formats first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last point is crucial.&lt;/p&gt;

&lt;p&gt;The more formats I support, the more information I must store to distinguish them.&lt;/p&gt;

&lt;p&gt;Up to 256 formats, one byte is enough.&lt;/p&gt;

&lt;p&gt;Beyond that, two are needed.&lt;/p&gt;

&lt;p&gt;The size/variety trade-off is permanent.&lt;/p&gt;

&lt;p&gt;While looking for the most common formats on my laptop — RFC 3339, ISO 8601, macOS logs — I quickly understood that the standards hid a forest of variants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ISO 8601 with nanoseconds UTC&lt;/li&gt;
&lt;li&gt;ISO 8601 UTC&lt;/li&gt;
&lt;li&gt;ISO 8601 with offset&lt;/li&gt;
&lt;li&gt;RFC 3339 with nanoseconds and offset&lt;/li&gt;
&lt;li&gt;and many more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To validate the principle, I did not need to be exhaustive.&lt;/p&gt;

&lt;p&gt;A sufficiently widespread reduced subset should already allow compression on many encountered cases.&lt;/p&gt;

&lt;p&gt;From there, the transformation applied by &lt;code&gt;Metarc&lt;/code&gt; can be understood in three steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Reduce the instant
&lt;/h2&gt;

&lt;p&gt;A dated moment is a point on a timeline.&lt;/p&gt;

&lt;p&gt;If you choose an origin, in computing often &lt;code&gt;January 1st 1970&lt;/code&gt;, it can be represented by a simple distance to that origin.&lt;/p&gt;

&lt;p&gt;For example, this date: &lt;code&gt;2026-05-11 10:36:19&lt;/code&gt;&lt;br&gt;
can be represented as a Unix timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Metarc&lt;/code&gt; encodes the instant in fixed numeric form on 8 bytes, with a granularity sufficient for the modern log formats targeted.&lt;/p&gt;

&lt;p&gt;So we transform a textual string of 19 bytes into a fixed numeric block of 8 bytes.&lt;/p&gt;

&lt;p&gt;Even if the date appears only once in the file.&lt;/p&gt;

&lt;p&gt;This has two important consequences:&lt;/p&gt;

&lt;p&gt;part of the gain comes from understanding the structure, not just from repetition;&lt;br&gt;
unlike classical statistical compression, a unique date can already be reduced efficiently.&lt;/p&gt;

&lt;p&gt;That is already useful.&lt;/p&gt;

&lt;p&gt;But it is only half of the problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2 — Restore the exact original format
&lt;/h2&gt;

&lt;p&gt;The same instant can be written in dozens of ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2026-05-11 10:36:19&lt;/li&gt;
&lt;li&gt;Mon May 11 10:36:19 2026&lt;/li&gt;
&lt;li&gt;11/May/2026:10:36:19&lt;/li&gt;
&lt;li&gt;2026/05/11T10:36:19Z&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not to mention timezones, milliseconds or nanoseconds.&lt;/p&gt;

&lt;p&gt;In reality, the number of possible formats is almost infinite.&lt;/p&gt;

&lt;p&gt;To restore the date identically, &lt;code&gt;Metarc&lt;/code&gt; must store both the timestamp and enough information about the original format.&lt;/p&gt;

&lt;p&gt;The trade-off is therefore permanent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect fast;&lt;/li&gt;
&lt;li&gt;encode fast;&lt;/li&gt;
&lt;li&gt;store little;&lt;/li&gt;
&lt;li&gt;remain more compact than the original date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first versions worked well.&lt;/p&gt;

&lt;p&gt;But not always better than zstd alone.&lt;/p&gt;

&lt;p&gt;That forced me to dig deeper.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3 — Help zstd by ordering bytes by entropy
&lt;/h2&gt;

&lt;p&gt;Once the timestamp and the format were encoded, a problem remained in the structure of the compressed format:&lt;/p&gt;

&lt;p&gt;the order of the bytes.&lt;/p&gt;

&lt;p&gt;A naive layout looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0x00][fmt_byte][uint64 timestamp][int16 tz_min][uint8 subsec_digits]
\__ Low ___/    \___ HIGH ___/    \___________ Low ________________/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The timestamp changes a lot.&lt;/p&gt;

&lt;p&gt;The format, timezone and precision usually change much less.&lt;/p&gt;

&lt;p&gt;So by reorganizing the format to group low-entropy data at the beginning, we create a longer repetitive sequence that zstd can compress better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0x00][fmt_byte][int16 tz_min][uint8 subsec_digits][uint64 timestamp]
\____________________ Low ________________________/ \___ HIGH ___/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metacompression acts here in two ways:&lt;/p&gt;

&lt;p&gt;it compresses the date itself;&lt;br&gt;
it optimizes the byte ordering for the downstream compressor.&lt;/p&gt;

&lt;p&gt;The knowledge of the structure — what changes a lot and what changes little — enables this double gain.&lt;/p&gt;

&lt;p&gt;That is the interesting part.&lt;/p&gt;

&lt;p&gt;Not just replacing text with binary.&lt;/p&gt;

&lt;p&gt;Preparing the data so that zstd sees a better byte stream.&lt;/p&gt;
&lt;h2&gt;
  
  
  Results on Loghub
&lt;/h2&gt;

&lt;p&gt;For my tests, I used Loghub, a corpus containing real log files produced by standard software.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Metarc&lt;/code&gt; archives files by applying &lt;code&gt;metacompression&lt;/code&gt; transformations and then compresses with zstd by default.&lt;/p&gt;

&lt;p&gt;That is why I compare it with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tar --zstd -cvf xxx.tar.zstd xxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;marc archive xxx.marc xxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On the Loghub corpus, with the formats currently recognized by log-date-subst/v2, Metarc gains up to 26.5% compared to tar+zstd.&lt;/p&gt;

&lt;p&gt;On unrecognized formats, the gain is logically 0%.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset&lt;/th&gt;
&lt;th&gt;Directory size&lt;/th&gt;
&lt;th&gt;tar+zstd size&lt;/th&gt;
&lt;th&gt;Metarc size&lt;/th&gt;
&lt;th&gt;Metacompression benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mac&lt;/td&gt;
&lt;td&gt;844K&lt;/td&gt;
&lt;td&gt;136K&lt;/td&gt;
&lt;td&gt;100K&lt;/td&gt;
&lt;td&gt;26.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenStack&lt;/td&gt;
&lt;td&gt;1.3M&lt;/td&gt;
&lt;td&gt;136K&lt;/td&gt;
&lt;td&gt;104K&lt;/td&gt;
&lt;td&gt;23.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HDFS&lt;/td&gt;
&lt;td&gt;708K&lt;/td&gt;
&lt;td&gt;136K&lt;/td&gt;
&lt;td&gt;112K&lt;/td&gt;
&lt;td&gt;17.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BGL&lt;/td&gt;
&lt;td&gt;776K&lt;/td&gt;
&lt;td&gt;136K&lt;/td&gt;
&lt;td&gt;116K&lt;/td&gt;
&lt;td&gt;14.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spark&lt;/td&gt;
&lt;td&gt;500K&lt;/td&gt;
&lt;td&gt;36K&lt;/td&gt;
&lt;td&gt;32K&lt;/td&gt;
&lt;td&gt;11.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSSH&lt;/td&gt;
&lt;td&gt;580K&lt;/td&gt;
&lt;td&gt;40K&lt;/td&gt;
&lt;td&gt;36K&lt;/td&gt;
&lt;td&gt;10.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HealthApp&lt;/td&gt;
&lt;td&gt;472K&lt;/td&gt;
&lt;td&gt;44K&lt;/td&gt;
&lt;td&gt;40K&lt;/td&gt;
&lt;td&gt;9.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;736K&lt;/td&gt;
&lt;td&gt;52K&lt;/td&gt;
&lt;td&gt;48K&lt;/td&gt;
&lt;td&gt;7.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zookeeper&lt;/td&gt;
&lt;td&gt;648K&lt;/td&gt;
&lt;td&gt;52K&lt;/td&gt;
&lt;td&gt;48K&lt;/td&gt;
&lt;td&gt;7.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apache&lt;/td&gt;
&lt;td&gt;432K&lt;/td&gt;
&lt;td&gt;28K&lt;/td&gt;
&lt;td&gt;28K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hadoop&lt;/td&gt;
&lt;td&gt;920K&lt;/td&gt;
&lt;td&gt;44K&lt;/td&gt;
&lt;td&gt;44K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HPC&lt;/td&gt;
&lt;td&gt;372K&lt;/td&gt;
&lt;td&gt;56K&lt;/td&gt;
&lt;td&gt;56K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;548K&lt;/td&gt;
&lt;td&gt;36K&lt;/td&gt;
&lt;td&gt;36K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxifier&lt;/td&gt;
&lt;td&gt;592K&lt;/td&gt;
&lt;td&gt;52K&lt;/td&gt;
&lt;td&gt;52K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thunderbird&lt;/td&gt;
&lt;td&gt;768K&lt;/td&gt;
&lt;td&gt;64K&lt;/td&gt;
&lt;td&gt;64K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;684K&lt;/td&gt;
&lt;td&gt;32K&lt;/td&gt;
&lt;td&gt;32K&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For recognized formats, the size gain brought by &lt;code&gt;metacompression&lt;/code&gt; is **14% on average.&lt;/p&gt;

&lt;p&gt;The gain depends directly on the proportion of dates recognized in the corpus.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;Metarc&lt;/code&gt; detects a format, it reduces the temporal information and reorganizes it for &lt;code&gt;zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When it detects none, the file simply follows the standard compression path.&lt;/p&gt;

&lt;p&gt;You can check the detail of the gain per archive with the &lt;code&gt;--explain&lt;/code&gt; flag:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;time marc archive --explain mac.marc Mac&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--- Plan Summary ---
Total entries:      4
Transforms applied: 1
Estimated gain:     104.0 KB

Breakdown by transform:
  log-date-subst/v2        1 applied      0 skipped  ~104.0 KB saved
  raw                      0 applied      3 skipped  ~0 B saved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What still needs improvement
&lt;/h2&gt;

&lt;p&gt;Implementing more formats without degrading performance remains an obvious axis for improvement.&lt;/p&gt;

&lt;p&gt;Adding a format can sometimes come down to encoding a simple variant, such as the date separator: / or -.&lt;/p&gt;

&lt;p&gt;But more often, it requires detecting a new pattern in a new set of log files.&lt;/p&gt;

&lt;p&gt;The real work is therefore to broaden coverage without blowing up the detection cost.&lt;/p&gt;

&lt;p&gt;There are also still many optimizations to implement.&lt;/p&gt;

&lt;p&gt;For example, some compressed storage formats could be specialized.&lt;/p&gt;

&lt;p&gt;No point keeping timestamps in uint64 format for formats that do not need nanoseconds.&lt;/p&gt;

&lt;p&gt;The current implementation validates the principle.&lt;/p&gt;

&lt;p&gt;It does not exhaust the idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real point: metacompression
&lt;/h2&gt;

&lt;p&gt;The real result of this exploration is not, for me, the average 14% compression gain.&lt;/p&gt;

&lt;p&gt;The interest of date compression is that it illustrates &lt;code&gt;metacompression&lt;/code&gt; in its most complete form:&lt;/p&gt;

&lt;p&gt;an upstream compression that adds to and optimizes downstream byte stream compression.&lt;/p&gt;

&lt;p&gt;That was Metarc’s bet:&lt;/p&gt;

&lt;p&gt;compress the structure before compressing the bytes.&lt;/p&gt;

&lt;p&gt;The next step will not play out on a hand-picked example, but on real data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;code repositories&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;technical archives&lt;/li&gt;
&lt;li&gt;heterogeneous corpora&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is how an intuition becomes a tool.&lt;/p&gt;

&lt;p&gt;If you have real logs with timestamp formats that Metarc does not handle yet, I would be very interested in testing them.&lt;/p&gt;

&lt;p&gt;Try &lt;code&gt;Metarc&lt;/code&gt;, compare it to &lt;code&gt;tar+zstd&lt;/code&gt;, and &lt;a href="https://github.com/arhuman/metarc-go/issues/new?template=feedback.md" rel="noopener noreferrer"&gt;share your results&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;And if you like the concept of &lt;code&gt;metacompression&lt;/code&gt; and want to give the project some visibility, a GitHub star is always appreciated.&lt;/p&gt;

</description>
      <category>compression</category>
      <category>logs</category>
      <category>go</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Structure Before Bytes: How Metarc Beats tar+zstd on Real Code</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Wed, 06 May 2026 01:35:12 +0000</pubDate>
      <link>https://dev.to/arhuman/structure-before-bytes-how-metarc-beats-tarzstd-on-real-code-19lg</link>
      <guid>https://dev.to/arhuman/structure-before-bytes-how-metarc-beats-tarzstd-on-real-code-19lg</guid>
      <description>&lt;p&gt;&lt;code&gt;tar+zstd&lt;/code&gt; is very hard to beat.&lt;/p&gt;

&lt;p&gt;So I stopped trying to beat it as a byte compressor.&lt;/p&gt;

&lt;p&gt;Instead, I tried something else:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;compress the structure first, then compress the bytes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the idea behind &lt;a href="https://github.com/arhuman/metarc-go" rel="noopener noreferrer"&gt;Metarc&lt;/a&gt;, a small experimental archiver written in Go.&lt;/p&gt;

&lt;p&gt;It explores what I call &lt;strong&gt;metacompression&lt;/strong&gt;: reducing structural and semantic redundancy across a source tree before applying a standard compressor such as &lt;code&gt;zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And on my current source-code benchmark corpus, Metarc is now smaller than &lt;code&gt;tar+zstd&lt;/code&gt; on every tested repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem: tar sees a stream, not a project
&lt;/h2&gt;

&lt;p&gt;Traditional archive pipelines are usually built around a simple idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;directory tree → tar stream → compressor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;This is robust, portable, simple, and battle-tested.&lt;/p&gt;

&lt;p&gt;But it also means that by the time compression starts, a rich source tree has already been flattened into a byte stream.&lt;/p&gt;

&lt;p&gt;A source-code repository is not just bytes.&lt;/p&gt;

&lt;p&gt;It contains structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repeated files&lt;/li&gt;
&lt;li&gt;duplicated licenses&lt;/li&gt;
&lt;li&gt;common boilerplate&lt;/li&gt;
&lt;li&gt;generated content&lt;/li&gt;
&lt;li&gt;repeated JSON structures&lt;/li&gt;
&lt;li&gt;logs with predictable patterns&lt;/li&gt;
&lt;li&gt;similar files across directories&lt;/li&gt;
&lt;li&gt;semantic redundancy that is easier to see before everything becomes a stream&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A byte-level compressor can still find many patterns, of course.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zstd&lt;/code&gt; is excellent.&lt;/p&gt;

&lt;p&gt;But some redundancy is easier to detect when the input is still a file tree.&lt;/p&gt;

&lt;p&gt;That is the core idea of Metarc.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is metacompression?
&lt;/h2&gt;

&lt;p&gt;Metacompression means compressing information &lt;strong&gt;above&lt;/strong&gt; the byte-stream level.&lt;/p&gt;

&lt;p&gt;Instead of asking only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;how can we compress this sequence of bytes?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Metarc also asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;what does this directory tree contain, and what redundancy exists before we turn it into a stream?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The current approach is roughly:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
source tree&lt;br&gt;
  → scan files&lt;br&gt;
  → analyze content&lt;br&gt;
  → detect redundancy&lt;br&gt;
  → apply structural / semantic transforms&lt;br&gt;
  → store catalog + blobs&lt;br&gt;
  → apply zstd&lt;br&gt;
  → .marc archive&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Metarc does not try to replace &lt;code&gt;zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It tries to give &lt;code&gt;zstd&lt;/code&gt; a better input.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current result
&lt;/h2&gt;

&lt;p&gt;On the current benchmark corpus, Metarc produces smaller archives than &lt;code&gt;tar+zstd&lt;/code&gt; on every tested source-code repository.&lt;/p&gt;

&lt;p&gt;A few examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repository&lt;/th&gt;
&lt;th&gt;tar+zstd&lt;/th&gt;
&lt;th&gt;marc&lt;/th&gt;
&lt;th&gt;Gain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes&lt;/td&gt;
&lt;td&gt;81.1M&lt;/td&gt;
&lt;td&gt;75.3M&lt;/td&gt;
&lt;td&gt;7.2% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;18.5M&lt;/td&gt;
&lt;td&gt;17.3M&lt;/td&gt;
&lt;td&gt;6.4% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;8.9M&lt;/td&gt;
&lt;td&gt;8.4M&lt;/td&gt;
&lt;td&gt;5.6% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumPy&lt;/td&gt;
&lt;td&gt;18.4M&lt;/td&gt;
&lt;td&gt;17.7M&lt;/td&gt;
&lt;td&gt;3.8% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Across the tested repositories, the gain is currently around &lt;strong&gt;3–7%&lt;/strong&gt; compared to &lt;code&gt;tar+zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That may sound modest.&lt;/p&gt;

&lt;p&gt;But beating &lt;code&gt;tar+zstd&lt;/code&gt; at all on real source-code repositories is already interesting, because the final compression step still uses a standard compressor.&lt;/p&gt;

&lt;p&gt;The difference comes from what happens before that final compression step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;A 3–7% improvement is not revolutionary by itself.&lt;/p&gt;

&lt;p&gt;The interesting part is not the number alone.&lt;/p&gt;

&lt;p&gt;The interesting part is that the improvement comes from changing the layer where compression starts.&lt;/p&gt;

&lt;p&gt;Most compression pipelines treat the file tree as something to serialize before compression.&lt;/p&gt;

&lt;p&gt;Metarc treats the file tree as something to analyze before compression.&lt;/p&gt;

&lt;p&gt;That opens the door to transforms that byte-stream compression does not naturally model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;global file deduplication&lt;/li&gt;
&lt;li&gt;semantic normalization&lt;/li&gt;
&lt;li&gt;repeated structure detection&lt;/li&gt;
&lt;li&gt;content-aware storage decisions&lt;/li&gt;
&lt;li&gt;corpus-aware compression strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially relevant for source-code repositories, where repetition often exists at a higher level than raw bytes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Speed results
&lt;/h2&gt;

&lt;p&gt;Metarc is also faster than &lt;code&gt;tar+zstd&lt;/code&gt; in my current cold-cache benchmark runs.&lt;/p&gt;

&lt;p&gt;But I want to be precise here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the speedup is not the core meta-compression claim.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The speed difference mostly comes from implementation choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;parallel scanning&lt;/li&gt;
&lt;li&gt;parallel hashing&lt;/li&gt;
&lt;li&gt;BLAKE3&lt;/li&gt;
&lt;li&gt;lightweight transforms&lt;/li&gt;
&lt;li&gt;avoiding some traditional archive pipeline costs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main claim of meta-compression is about archive size.&lt;/p&gt;

&lt;p&gt;The speed results are interesting, but they should not be confused with the compression idea itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What these benchmarks do not prove
&lt;/h2&gt;

&lt;p&gt;These results do &lt;strong&gt;not&lt;/strong&gt; prove that Metarc is universally better than &lt;code&gt;tar+zstd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They do not prove that this approach wins on every kind of data.&lt;/p&gt;

&lt;p&gt;They do not prove that &lt;code&gt;.marc&lt;/code&gt; should replace &lt;code&gt;.tar.zst&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They show something narrower and, I think, more interesting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;on the tested source-code repositories, there is enough structural redundancy outside the byte stream to make meta-compression measurable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Different datasets may behave very differently.&lt;/p&gt;

&lt;p&gt;For example, I would not expect the same kind of gains on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;already compressed media&lt;/li&gt;
&lt;li&gt;random binary blobs&lt;/li&gt;
&lt;li&gt;encrypted data&lt;/li&gt;
&lt;li&gt;image-heavy repositories&lt;/li&gt;
&lt;li&gt;small directories with little repetition&lt;/li&gt;
&lt;li&gt;corpora where &lt;code&gt;zstd&lt;/code&gt; already captures most of the redundancy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is still experimental.&lt;/p&gt;

&lt;p&gt;The goal is not to declare victory over &lt;code&gt;tar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The goal is to explore what happens when compression starts from a richer model of the input.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmark methodology
&lt;/h2&gt;

&lt;p&gt;The benchmark is designed to compare Metarc against a realistic baseline:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
tar + zstd&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The current benchmark methodology uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;real open-source repositories&lt;/li&gt;
&lt;li&gt;pinned repository revisions&lt;/li&gt;
&lt;li&gt;the same machine for all runs&lt;/li&gt;
&lt;li&gt;median of multiple runs&lt;/li&gt;
&lt;li&gt;cold cache by default for timing&lt;/li&gt;
&lt;li&gt;direct comparison against &lt;code&gt;tar+zstd&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;round-trip verification mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmark scripts are included in the repository.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
./scripts/run_bench.sh --type size&lt;br&gt;
./scripts/run_bench.sh --type time&lt;br&gt;
./scripts/compare_on_repo.sh --mode test&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The full benchmark page is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arhuman/metarc-go/blob/main/docs/benchmarks.md" rel="noopener noreferrer"&gt;https://github.com/arhuman/metarc-go/blob/main/docs/benchmarks.md&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why cold cache?
&lt;/h2&gt;

&lt;p&gt;Benchmarking archive tools is tricky.&lt;/p&gt;

&lt;p&gt;A hot-cache run can mostly measure CPU and compression speed.&lt;/p&gt;

&lt;p&gt;A cold-cache run includes more of the real end-to-end cost of archiving a source tree from disk.&lt;/p&gt;

&lt;p&gt;Both are useful, but they answer different questions.&lt;/p&gt;

&lt;p&gt;For now, the default benchmark uses cold cache because it better represents the practical operation of archiving a repository.&lt;/p&gt;

&lt;p&gt;That said, the distinction matters.&lt;/p&gt;

&lt;p&gt;One thing I learned while working on the benchmark is that methodology can change the interpretation dramatically.&lt;/p&gt;

&lt;p&gt;So if you look at the numbers, please look at the methodology too.&lt;/p&gt;

&lt;p&gt;Benchmarks without context are just numerology with better fonts.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Metarc currently does
&lt;/h2&gt;

&lt;p&gt;Metarc is still experimental, but the current architecture already includes the core pieces needed to explore this idea:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;text&lt;br&gt;
scan&lt;br&gt;
  → analyze&lt;br&gt;
  → plan&lt;br&gt;
  → store&lt;br&gt;
  → compress&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At a high level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Metarc scans the source tree.&lt;/li&gt;
&lt;li&gt;It analyzes files and metadata.&lt;/li&gt;
&lt;li&gt;It detects redundancy and chooses transforms.&lt;/li&gt;
&lt;li&gt;It stores a catalog and content blobs.&lt;/li&gt;
&lt;li&gt;It compresses the final archive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important part is that the archive format is not only a serialized tar stream.&lt;/p&gt;

&lt;p&gt;It contains a representation of the structure Metarc discovered.&lt;/p&gt;

&lt;p&gt;That gives the format room to evolve.&lt;/p&gt;




&lt;h2&gt;
  
  
  What could come next
&lt;/h2&gt;

&lt;p&gt;The current results are encouraging, but this is still early.&lt;/p&gt;

&lt;p&gt;Some possible next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stronger file-level deduplication&lt;/li&gt;
&lt;li&gt;repeated boilerplate detection&lt;/li&gt;
&lt;li&gt;license block factoring&lt;/li&gt;
&lt;li&gt;JSON normalization&lt;/li&gt;
&lt;li&gt;log normalization&lt;/li&gt;
&lt;li&gt;generated-file detection&lt;/li&gt;
&lt;li&gt;language-aware transforms&lt;/li&gt;
&lt;li&gt;better corpus analysis&lt;/li&gt;
&lt;li&gt;more benchmark repositories&lt;/li&gt;
&lt;li&gt;benchmark history per release&lt;/li&gt;
&lt;li&gt;stronger archive verification tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am especially interested in transforms that are simple, explainable, and reversible.&lt;/p&gt;

&lt;p&gt;The goal is not to invent a magical compressor.&lt;/p&gt;

&lt;p&gt;The goal is to find practical cases where knowing more about the input lets us compress it better.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Go?
&lt;/h2&gt;

&lt;p&gt;Metarc is written in Go because the problem fits Go well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;file tree walking&lt;/li&gt;
&lt;li&gt;concurrency&lt;/li&gt;
&lt;li&gt;streaming I/O&lt;/li&gt;
&lt;li&gt;simple binaries&lt;/li&gt;
&lt;li&gt;good standard library&lt;/li&gt;
&lt;li&gt;easy distribution&lt;/li&gt;
&lt;li&gt;predictable performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is also a good language for building experimental infrastructure tools without turning the codebase into a research prototype that only runs on the author’s laptop during a full moon.&lt;/p&gt;

&lt;p&gt;Go keeps the project boring in the right places.&lt;/p&gt;

&lt;p&gt;That is useful when the idea itself is already unusual.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is this production-ready?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Metarc is usable, but it should still be treated as experimental.&lt;/p&gt;

&lt;p&gt;The format may evolve.&lt;/p&gt;

&lt;p&gt;The transforms may change.&lt;/p&gt;

&lt;p&gt;The benchmark corpus will expand.&lt;/p&gt;

&lt;p&gt;The implementation will likely be rewritten in parts as the design becomes clearer.&lt;/p&gt;

&lt;p&gt;For now, I see it as a playground for exploring compression strategies above the byte-stream level.&lt;/p&gt;

&lt;p&gt;If it becomes useful as a real archiver, great.&lt;/p&gt;

&lt;p&gt;But the first goal is to test the idea properly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core idea
&lt;/h2&gt;

&lt;p&gt;The shortest way to summarize Metarc is this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`text&lt;br&gt;
tar compresses a byte stream.&lt;/p&gt;

&lt;p&gt;Metarc compresses a source tree.&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That difference is now measurable on my benchmark corpus.&lt;/p&gt;

&lt;p&gt;And that is what makes the project interesting to me.&lt;/p&gt;

&lt;p&gt;Not because &lt;code&gt;tar+zstd&lt;/code&gt; is bad.&lt;/p&gt;

&lt;p&gt;It is not.&lt;/p&gt;

&lt;p&gt;But because source-code repositories contain structure, and maybe compression tools should exploit more of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Feedback wanted
&lt;/h2&gt;

&lt;p&gt;I am especially looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;criticism of the benchmark methodology&lt;/li&gt;
&lt;li&gt;source-code repositories with unusual redundancy&lt;/li&gt;
&lt;li&gt;ideas for reversible semantic transforms&lt;/li&gt;
&lt;li&gt;references to similar projects or papers&lt;/li&gt;
&lt;li&gt;cases where this approach should fail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arhuman/metarc-go" rel="noopener noreferrer"&gt;https://github.com/arhuman/metarc-go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The benchmark page is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arhuman/metarc-go/blob/main/docs/benchmarks.md" rel="noopener noreferrer"&gt;https://github.com/arhuman/metarc-go/blob/main/docs/benchmarks.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you know a repository that would be a good stress test, I would love to try it.&lt;/p&gt;

</description>
      <category>compression</category>
      <category>go</category>
      <category>tooling</category>
      <category>datastructures</category>
    </item>
    <item>
      <title>Trying to beat the venerable tar</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Mon, 27 Apr 2026 01:53:29 +0000</pubDate>
      <link>https://dev.to/arhuman/trying-to-beat-the-venerable-tar-2nh</link>
      <guid>https://dev.to/arhuman/trying-to-beat-the-venerable-tar-2nh</guid>
      <description>&lt;p&gt;Hi,&lt;/p&gt;

&lt;p&gt;I’ve been working on a small Go project called &lt;a href="https://github.com/arhuman/metarc-go" rel="noopener noreferrer"&gt;Metarc&lt;/a&gt;: It's an Open Source file archiver and I’d be curious to get feedback from the community.&lt;/p&gt;

&lt;p&gt;The idea is to explore “&lt;a href="https://blog-test.assad.fr/en/post/what_is_metacompression/" rel="noopener noreferrer"&gt;metacompression&lt;/a&gt;”: instead of only compressing bytes, try to reduce structural and semantic redundancy across files first (licenses, JSON, logs, duplicated content…), then apply a standard compressor.&lt;/p&gt;

&lt;p&gt;On early repository benchmarks, it’s already:&lt;br&gt;
_ 22% smaller thant &lt;code&gt;tar + zstd&lt;/code&gt; on very specific kind of archives&lt;br&gt;
(Code source with lot of redundancies)&lt;br&gt;
_ faster than &lt;code&gt;tar&lt;/code&gt;&lt;br&gt;
_ with archive sizes often in the same range on popular github repos&lt;/p&gt;

&lt;p&gt;It’s still experimental, but &lt;strong&gt;already usable&lt;/strong&gt; and mainly intended as a playground for experimenting with compression strategies.&lt;/p&gt;

&lt;p&gt;Would love to hear your thoughts or ideas on the subject.&lt;/p&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>contributorswanted</category>
      <category>cli</category>
    </item>
    <item>
      <title>Your Servers Deserve Better: Meet Minexus, a Smart Admin Agent System in Go</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Tue, 01 Jul 2025 00:48:30 +0000</pubDate>
      <link>https://dev.to/arhuman/your-server-deserves-better-meet-minexus-a-smart-admin-agent-system-in-go-41gn</link>
      <guid>https://dev.to/arhuman/your-server-deserves-better-meet-minexus-a-smart-admin-agent-system-in-go-41gn</guid>
      <description>&lt;h2&gt;
  
  
  Meet Minexus — A Modular, Distributed Admin System in Go
&lt;/h2&gt;

&lt;p&gt;I was tired of managing my servers with brittle scripts, ad hoc SSH sessions, and clunky monitoring tools. So I built &lt;a href="https://github.com/arhuman/minexus" rel="noopener noreferrer"&gt;Minexus&lt;/a&gt;, a modular platform to monitor and control servers via secure agents, with Go and gRPC under the hood.&lt;/p&gt;

&lt;p&gt;If you’ve ever wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To send a command to 50 machines and get results back fast&lt;/li&gt;
&lt;li&gt;To build your own admin plugins with Go&lt;/li&gt;
&lt;li&gt;To manage your servers like a well-oiled, distributed system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then this might be up your alley.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/arhuman/minexus" rel="noopener noreferrer"&gt;Minexus&lt;/a&gt; is made of 3 main components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nexus&lt;/strong&gt; — the central server, connected to a PostgreSQL DB&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minions&lt;/strong&gt; — lightweight agents running on your hosts, communicating with the Nexus via gRPC + mTLS&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console&lt;/strong&gt; — an admin UI and command interface, also talking to the Nexus&lt;/p&gt;

&lt;p&gt;Minions register periodically. Commands go through the Nexus, and results are logged/stored. Want a new command? Just write a command.&lt;/p&gt;

&lt;p&gt;It’s simple, extensible, and built for sysadmins/devops/devs who want control without vendor lock-in.&lt;/p&gt;

&lt;p&gt;Use Cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remote command execution (with return capture)&lt;/li&gt;
&lt;li&gt;Service restarts across hosts&lt;/li&gt;
&lt;li&gt;Health checks / monitoring plugins&lt;/li&gt;
&lt;li&gt;Security scans (CVE lookup, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anything you can plug into a Go module...&lt;/p&gt;

&lt;p&gt;Want to send restart-service nginx to all your production servers and get clean results in seconds? Minexus can do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;It's early days, but it’s usable and growing. Contributors welcome — the command system (soon a plugin system) makes it a playground for Go devs.&lt;/p&gt;

&lt;p&gt;You're not a coder, it's not a problem: I’d love 🙏 &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feedback on the architecture&lt;/li&gt;
&lt;li&gt;Suggestions for useful commands/plugins&lt;/li&gt;
&lt;li&gt;Help testing on non-Linux environments&lt;/li&gt;
&lt;li&gt;Ideas to make this your go-to internal admin framework&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s Build This Together
&lt;/h2&gt;

&lt;p&gt;I believe sysadmin/devops tooling should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to use&lt;/li&gt;
&lt;li&gt;Hackable&lt;/li&gt;
&lt;li&gt;Fun to extend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you agree, give Minexus a spin, drop a comment, or open an issue.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/arhuman/minexus" rel="noopener noreferrer"&gt;https://github.com/arhuman/minexus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>security</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Why I like generics in golang</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Fri, 31 Jul 2020 22:20:33 +0000</pubDate>
      <link>https://dev.to/arhuman/why-i-like-generics-in-golang-19m3</link>
      <guid>https://dev.to/arhuman/why-i-like-generics-in-golang-19m3</guid>
      <description>&lt;p&gt;(article originally written &lt;a href="https://blog.assad.fr/post/go_generics/" rel="noopener noreferrer"&gt;on my blog &lt;strong&gt;in French&lt;/strong&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I was reading again the excellent article from Ian Taylon and Robert Grisemeer (&lt;a href="https://blog.golang.org/generics-next-step" rel="noopener noreferrer"&gt;The next step for generics&lt;/a&gt;) and I couldn't help thinking that I love the way we're heading. In fact, I love so much those new generics that I've decided to write an article to claim it.&lt;/p&gt;

&lt;p&gt;With the latest drafts published, you should all have a precise idea about what the generics will look like in the next version of Go. So rather than writing another technical review about the changes, I'll rather state why I like those generics because it's the exact same reasons why I like the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  I like generics because they're simple
&lt;/h2&gt;

&lt;p&gt;As type parameters are special parameters, they're now handle as parameters (after the function name) but in an optional distinct list starting with the '&lt;em&gt;type&lt;/em&gt;' keyword and located before the usual parameters list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// do something with the slice of T&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call is similar to a standard call, specifying the type just before the parameters list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)([]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some cases (when all the types are used for the input parameter types and not in the body) the compiler is even able to deduce the type from the parameter types.&lt;/p&gt;

&lt;p&gt;Constraints are now defined through interface type (no more contracts). For example, if we want the type T to implement String() we just have to add the Stringer interface constraint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Stringer is a type constraint that requires a String method.&lt;/span&gt;
&lt;span class="c"&gt;// The String method should return a string representation of the value.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Stringer&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;Stringer&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// do something with the slice of T, and call String() on slice elements&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we want to put a constraint on an operator, we can now use base types in an interface type by prefixing the list of base types with '&lt;em&gt;type&lt;/em&gt;'.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Ordered is a type constraint that matches any ordered type.&lt;/span&gt;
&lt;span class="c"&gt;// An ordered type is one that supports the &amp;lt;, &amp;lt;=, &amp;gt;, and &amp;gt;= operators.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Ordered&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uintptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to make your life even simple, a new type constraint '&lt;em&gt;comparable&lt;/em&gt;' is now available to handle  '==' and '!=' operators&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Index returns the index of x in s, or -1 if not found.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;comparable&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Now you can compare elements of slice even if they're struct or array&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, isn't it?&lt;/p&gt;

&lt;h2&gt;
  
  
  I like generics because I like Gophers' community spirit
&lt;/h2&gt;

&lt;p&gt;But beyond the feature added to the language, what I like with those new generics, is that the way they were added adhere to the &lt;strong&gt;community spirit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;you have to remember that generics were the 3rd point (with dependencies/package and errors handling) considered as the most important to improve according to &lt;a href="https://blog.golang.org/survey2016-results" rel="noopener noreferrer"&gt;2016 Go users survey&lt;/a&gt; and 2017 one.&lt;/p&gt;

&lt;p&gt;The fact that language evolution has been initiated based on the community feedback (rather than on choices made by a "benevolent dictator for life") is already great.&lt;/p&gt;

&lt;p&gt;The pace at which the features were introduced is also an interesting metric:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modules handling (introduced in version 1.11 in 2018)&lt;/li&gt;
&lt;li&gt;Errors handling (introduced in version 1.13 in 2019)&lt;/li&gt;
&lt;li&gt;Generic introduction (executed in version 1.15 due for end of 2020)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we see, the release pace is quite fast but not rushed.&lt;/p&gt;

&lt;h2&gt;
  
  
  I like generics because I like Go's philosophy
&lt;/h2&gt;

&lt;p&gt;Lastly, I like generics because they comply with the Go's philosophy.&lt;br&gt;
(since the &lt;a href="https://blog.golang.org/survey2016-results" rel="noopener noreferrer"&gt;Go Brand Book&lt;/a&gt; published in 2018, I'd rather use the word &lt;em&gt;values&lt;/em&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Simple: As seen above those generic is simple (bye bye contracts) with few language modifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient: With every draft, performance has been a constraint and the last one manage to allow you to choose between faster compilation and slower execution &lt;em&gt;and&lt;/em&gt; the contrary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thoughtful: Because instead of implementing generics based on another language, the community took its time to design one complying to the spirit of the language, to write drafts, to discuss them, to improve what can be improved and do it again to reach an implementation which complies to the language objectives and spirit without sacrificing to performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I like generics because it's practical
&lt;/h2&gt;

&lt;p&gt;Go being a pragmatic language, you can already test this generic implementation on &lt;a href="https://go2goplay.golang.org/" rel="noopener noreferrer"&gt;go2go  playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But as I tend to be optimistic and enthusiastic, maybe I got carried away, so let me ask you: And you, What do you think about this generics implementation?&lt;/p&gt;

</description>
      <category>go</category>
      <category>generics</category>
      <category>community</category>
    </item>
    <item>
      <title>How could you pretend to be Agile if you don't even know Scrum rituals?</title>
      <dc:creator>arhuman</dc:creator>
      <pubDate>Tue, 03 Sep 2019 13:06:47 +0000</pubDate>
      <link>https://dev.to/arhuman/how-could-you-pretend-to-be-agile-if-you-don-t-even-know-scrum-rituals-5bfe</link>
      <guid>https://dev.to/arhuman/how-could-you-pretend-to-be-agile-if-you-don-t-even-know-scrum-rituals-5bfe</guid>
      <description>&lt;p&gt;&lt;small&gt;(Article originally posted on &lt;a href="https://blog.assad.fr/en/post/agile_without_scrum/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;That's more or less what I've been asked in a recent (failed) interview.&lt;br&gt;
That was more subtle of course, but after being corrected on Scrum terminology,&lt;br&gt;
failing to recognize the prevalence of the retrospective over the other rituals probably sealed the outcome of the interview.&lt;/p&gt;

&lt;p&gt;I clearly didn't convinced my interviewer. My last Scrum experience was ten years ago. And would probably be considered as "Faux Agile" in actual terminology. So he was probably allowed to assert that I wouldn't be a good Scrum Master. But does that mean that I was not Agile?&lt;/p&gt;

&lt;p&gt;As a pragmatic person, I neither stubbornly rejected his assertion nor did I slavishly waived my belief.&lt;br&gt;
I did some work: I've read books and articles and I've asserted my processes and values.&lt;/p&gt;

&lt;p&gt;Yes, values...&lt;br&gt;
Because to me it allways boils down to values.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agile Manifesto
&lt;/h2&gt;

&lt;p&gt;To understant why, let's get back in time, in 2001 to be precise.&lt;br&gt;
Because it's in 2001 that the Agile movement was born.&lt;br&gt;
Seventeen Software developers, published what is now known as the "Agile Manifesto".&lt;br&gt;
This 68 words long text is considered to be the basis of the Agile movement.&lt;br&gt;
But most important to me, they also proclaim 4 values that define what we now call Agility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Individuals and Interactions&lt;/strong&gt; over processes and tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working Software&lt;/strong&gt; over comprehensive documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Collaboration&lt;/strong&gt; over contract negotiation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responding to Change&lt;/strong&gt; over following a plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time they also presented 12 principles to enforce and develop those values but that's out of the scope of this article.&lt;/p&gt;

&lt;p&gt;Regarding those values I could definitely consider myself as Agile.&lt;br&gt;
I praise those values, and incidently I also follows several principles. And if you adhere to the Open Source culture you also probably do: The KISS principle, the “release early release often motto” are common illustrations of some of those principles.&lt;/p&gt;

&lt;h2&gt;
  
  
  eXtreme Programming
&lt;/h2&gt;

&lt;p&gt;Going further, I discovered that prior to the Agile Manifesto, other (now considered) Agile methodologies existed, eXtreme Programming is one of those.&lt;/p&gt;

&lt;p&gt;It also have values&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communication&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feedback&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Respect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Courage&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It happened that XP is also the first methodology I encountered as an Open Source software developer.&lt;br&gt;
So without surprise, I also integrated those values long ago.&lt;/p&gt;

&lt;p&gt;XP also defined several rules, similar to the Agile Manifesto principles.&lt;br&gt;
Again, many rules will seems familiar to any Open Source software developer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrate Often&lt;/li&gt;
&lt;li&gt;All code must have unit tests.&lt;/li&gt;
&lt;li&gt;All code must pass all unit tests before it  can be released.&lt;/li&gt;
&lt;li&gt;All production code is pair programmed.&lt;/li&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And from this rules derived practices: Continuous integration, Test Driven Development, Pair programming...&lt;/p&gt;

&lt;p&gt;Let's recap I check all the values, most of the rules, and several practices (especially as a &lt;a href="http://cpanwiki.grango.org/" rel="noopener noreferrer"&gt;CPANtester&lt;/a&gt;). So am I good, or is there something special about SCRUM that I miss?&lt;/p&gt;

&lt;h2&gt;
  
  
  Scrum
&lt;/h2&gt;

&lt;p&gt;Let's see Scrum Values&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Focus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Courage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Openness&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commitment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Respect&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You probably noticed that it has 2 values in common with XP, the 3 remaining 'Focus', 'Openness' and 'Commitment' are related to the Scrum team.&lt;/p&gt;

&lt;p&gt;Maybe we have an hint here.&lt;br&gt;
As a XP developer, I feel I can claim an Agile ability. But in a Scrum Team ?&lt;/p&gt;

&lt;p&gt;Sure some of the Scrum rituals are also XP practice (daily standing meeting) but as a single developer, it was not the practices I used.&lt;/p&gt;

&lt;p&gt;Some people consider that Agility only make sense as a team member.&lt;br&gt;
I can't just dismiss this belief but allow me to find it debatable: XP values does not require any team, and even the Agile Manifesto mention&lt;br&gt;
individuals and interactions but without any precision this could well be related to a developer and its customer.&lt;/p&gt;

&lt;p&gt;IMHO, Agility is all about improvement: team improvement, process improvement, technical improvement and self improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kanban
&lt;/h2&gt;

&lt;p&gt;For completness (Scrum, Kanban, XP being the 3 most used methodologies) here are the Kanban values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Understanding&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agreement&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Respect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leadership&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flow&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer focus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Balance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a perceptive reader you might have spotted the 'Respect' value which is common to the others methodology. &lt;br&gt;
To be honnest, I've never had the feeling that Kanban values were central to the methodology.&lt;br&gt;
In what I've read, the core practices are often highlighted, and most of the time the values wheren’t even listed. &lt;br&gt;
But may be I'm biased, I'm not sure people know XP values more than TDD or pair programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Back to the original question, I'm confident saying that I'm Agile even if I'm not an experienced Scrum Master or even practicionner.&lt;br&gt;
First, because Scrum isn't the only Agile methodology out there and besides XP there are also Kanban, RAD, Lean SD, Wild Agile and many others.&lt;br&gt;
Then and above all, because I follow/praise/put in practice values which are at the heart of many Agile methodologies (including Scrum). &lt;/p&gt;

&lt;p&gt;Going further I think that the simple fact of restricting Agility to a process knowledge is an anti-Agile pattern to me (Remember "Individuals and Interactions over processes and tools"?)&lt;/p&gt;

&lt;p&gt;That doesnt mean Rituals/practices are useless, they are a good way to check that you actually enforce the values you pretend to follow.&lt;br&gt;
But they are only meaningfull if you remember and adhere to the associated values:&lt;br&gt;
Attending a daily standing melee, with people you don't respect, staying silent on the encountered issues to hide that you screwed your task because you're just lazy is by no mean 'Agile'.&lt;/p&gt;

&lt;p&gt;On my side, I'm aware that rituals/practices are the best way to enforce/check those values and I will go on improving my knowledge of all rituals/practices and of the associated principle. After all constant improvement is one of the 12 principles of the Agile Manifesto...&lt;/p&gt;

&lt;h3&gt;
  
  
  Credits
&lt;/h3&gt;

&lt;p&gt;I'd like to thanks my peers from Happy Dev for their reviews/advices/insights.&lt;br&gt;
And I'd like to express my gratitude to the interviewer mentioned in the article: he forced me to re-think my Agile stance, convinced me to improve my Scrum knowledge and reminded me that self-improvement is a daily duty.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.extremeprogramming.org" rel="noopener noreferrer"&gt;eXtreme Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kanbantool.com/kanban-library/why-kanban/introducing-kanban-through-its-values" rel="noopener noreferrer"&gt;Kanban Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.scrumalliance.org/learn-about-scrum/scrum-values" rel="noopener noreferrer"&gt;Scrum Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ovid.github.io/wildagile.html" rel="noopener noreferrer"&gt;WildAgile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>scrum</category>
      <category>values</category>
      <category>agile</category>
    </item>
  </channel>
</rss>
