<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://robinpokorny.com/atom.xml" rel="self" type="application/atom+xml" /><link href="https://robinpokorny.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-08-12T19:51:09+00:00</updated><id>https://robinpokorny.com/atom.xml</id><title type="html">Robin Pokorny</title><subtitle>Sr Staff Engineer at Ataccama, meet-up organiser, podcaster</subtitle><author><name>Robin Pokorny</name></author><entry><title type="html">The Array Modeling Problem Every JSON Merge Patch API Eventually Hits</title><link href="https://robinpokorny.com/blog/the-array-modeling-problem-every-json-merge-patch-api-eventually-hits/" rel="alternate" type="text/html" title="The Array Modeling Problem Every JSON Merge Patch API Eventually Hits" /><published>2026-08-12T19:43:00+00:00</published><updated>2026-08-12T19:43:00+00:00</updated><id>https://robinpokorny.com/blog/the-array-modeling-problem-every-json-merge-patch-api-eventually-hits</id><content type="html" xml:base="https://robinpokorny.com/blog/the-array-modeling-problem-every-json-merge-patch-api-eventually-hits/"><![CDATA[<p>We use RFC 7396 JSON Merge Patch across our public API. It’s simple, it’s well specified, and clients like it.</p>

<p>(Note: not to be confused with RFC 6902 JSON Patch, which is much more complicated.)</p>

<p>JSON Merge Patch acts like a simple ‘diff’. The patch document mirrors the structure of the document you want to change. To add or update a field, you send the new value. To delete a field, you set the value to <code class="language-plaintext highlighter-rouge">null</code>. The rest stays as it was. Simple.</p>

<p>Then we hit arrays.</p>

<h2 id="the-problem">The problem</h2>

<p>JSON Merge Patch replaces arrays as a whole. That’s not a bug, it’s the spec.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">GET</span><span class="w">
</span><span class="p">{</span><span class="nl">"tags"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"draft"</span><span class="p">,</span><span class="w"> </span><span class="s2">"internal"</span><span class="p">,</span><span class="w"> </span><span class="s2">"q3"</span><span class="p">]}</span><span class="w">

</span><span class="err">//</span><span class="w"> </span><span class="err">PATCH</span><span class="w">
</span><span class="err">//</span><span class="w"> </span><span class="err">You</span><span class="w"> </span><span class="err">only</span><span class="w"> </span><span class="err">want</span><span class="w"> </span><span class="err">to</span><span class="w"> </span><span class="err">remove</span><span class="w"> </span><span class="s2">"internal"</span><span class="err">,</span><span class="w"> </span><span class="err">but</span><span class="w"> </span><span class="err">the</span><span class="w"> </span><span class="err">patch</span><span class="w"> </span><span class="err">document</span><span class="w">
</span><span class="err">//</span><span class="w"> </span><span class="err">has</span><span class="w"> </span><span class="err">no</span><span class="w"> </span><span class="err">way</span><span class="w"> </span><span class="err">to</span><span class="w"> </span><span class="err">say</span><span class="w"> </span><span class="s2">"remove one element"</span><span class="err">.</span><span class="w"> </span><span class="err">You</span><span class="w"> </span><span class="err">send</span><span class="w"> </span><span class="err">the</span><span class="w"> </span><span class="err">whole</span><span class="w"> </span><span class="err">array.</span><span class="w">
</span><span class="p">{</span><span class="nl">"tags"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"draft"</span><span class="p">,</span><span class="w"> </span><span class="s2">"q3"</span><span class="p">]}</span><span class="w">
</span></code></pre></div></div>

<p>One of our teams ran into this first, on a real feature, not a thought experiment. They brought it to our architecture forum as a high-level question: what do we do when JSON Merge Patch and arrays stop getting along. That’s usually where these things stall, a good question with no clear owner. So a few of us met with the team again and went through it properly.</p>

<p>The problem turned out to have two different shapes, not one.</p>

<p>The first is that arrays were often used in for a set, which JSON doesn’t have. You don’t care what was there before. You just want to add something, remove something, and move on. The mechanic forces you to reconstruct and resend the whole thing every time, even though your actual intent was one small delta.</p>

<p>The second, and the more interesting one, is sub-objects which are more complex and can have an internal state. Replacing the whole array means the client has to re-parse every element on every patch, even the ones that haven’t changed. If something in the UI was rendered from that sub-object, a full-array replace could reset it, because the client had no signal that most of what came back was untouched. In our case, some of these sub-objects were, honestly, sub-resources with a life of their own. But they felt like a natural part of the parent, changed often at the same time as the parent itself, and that’s exactly why they got modeled as an array in the first place.</p>

<p>The discussion that followed was the good kind, the kind where people push back because they actually care about getting it right. The sticking point wasn’t technical. It was that exposing a shape in the public API that didn’t match how we stored or treated the data internally felt, to some people meeting the idea for the first time, like a kind of dishonesty. If it’s a map on the wire, shouldn’t it be a map everywhere?</p>

<p>We talked it through. The contract and the storage don’t have to agree, and they usually shouldn’t. A public API is a promise to clients about how they can interact with a resource, not a mirror of your schema. Once that separation clicked, most of the discomfort went with it, and we converged on a default within the day.</p>

<p>Below are the options we actually put on the table, roughly in order of how much they change what you’re modeling. Our default, the shape we reach for unless something specific argues otherwise, is Option 1 for anything simple and Option 4 for anything with real per-item lifecycle. The rest are here because they’re real tools, not runners-up, and the right call depends on your resource, not on ours. Maybe they will inspire you.</p>

<h2 id="option-1-stay-with-the-array">Option 1: Stay with the array</h2>

<p>Accept that a change means resending the whole thing.</p>

<p>This is fine, and honestly the easiest choice, for short arrays of simple values, or arrays of value objects with no independent identity. Labels, a handful of monetary amounts, ID references.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"amounts"</span><span class="p">:</span><span class="w"> </span><span class="p">[{</span><span class="nl">"currency"</span><span class="p">:</span><span class="w"> </span><span class="s2">"EUR"</span><span class="p">,</span><span class="w"> </span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">},</span><span class="w"> </span><span class="p">{</span><span class="nl">"currency"</span><span class="p">:</span><span class="w"> </span><span class="s2">"USD"</span><span class="p">,</span><span class="w"> </span><span class="nl">"value"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="p">}]}</span><span class="w">
</span></code></pre></div></div>

<p>It gets uncomfortable the moment you’re thinking of the array as a set, where position never mattered, when the list gets long and changes often, or the moment the elements are complex enough that a client shouldn’t have to reparse all of them just because one changed.</p>

<p>If nothing about your collection has a life of its own, don’t give it one just to look sophisticated.</p>

<h2 id="option-2-index-as-key">Option 2: Index as key</h2>

<p>A middle ground before you commit to real ids: keep the collection positional, the way arrays in JavaScript work under the hood, but expose it as an object keyed by index instead of a JSON array.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">GET</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"0"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"one"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"two"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"2"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"three"</span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Number keys are technically strings in JSON, same as they are in a JavaScript object, so this pattern is somewhat established. You get per-slot patching without inventing any id scheme:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">PATCH</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"changed"</span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>You can even accept both shapes on write, a JSON array or a string-numbered dictionary, and normalize internally. That’s a nice bridge if you don’t want to break existing clients that still send arrays while letting newer clients patch by index.</p>

<p>The catch is the one we already ran into with plain arrays: position is not identity. Insert at the front, and every later index now points at a different element than it did a moment ago. Same with delete.</p>

<p>This option is worth reaching for only when the collection is truly positional and clients aren’t going to reorder or splice it mid-life. The moment reordering or deletion becomes routine, you’ve quietly outgrown this option and want real ids, which is Option 3.</p>

<h2 id="option-3-give-elements-an-id-model-the-collection-as-a-map">Option 3: Give elements an id, model the collection as a map</h2>

<p>Turn the array into an object keyed by id. Now the standard JSON Merge Patch semantics apply per element: send a key to update it, send <code class="language-plaintext highlighter-rouge">null</code> to delete it, leave a key out and it’s untouched.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">GET</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"a1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"one"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"a2"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"two"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"a3"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"three"</span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="err">//</span><span class="w"> </span><span class="err">PATCH</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"a2"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"changed"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"a1"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>This is the point where the storage-versus-contract question comes up, and it’s worth being direct about it, since it’s exactly what our own team pushed back on. What you expose in the public API doesn’t have to match what’s in your database. If you’re already storing these as an array internally, that’s fine, you’re free to keep it that way and only shape the id-keyed map at the API boundary. The contract is a promise about interaction, not a confession about your schema.</p>

<p>The ids themselves don’t need to be global. They just need to be stable to this context, so the same id comes back every time a client reads the resource. If there’s already a natural field that can serve as one, this is close to free. If there isn’t, minting one purely for this purpose is still a reasonable thing to do.</p>

<h2 id="option-4-server-generated-ids-with-a-placeholder-convention">Option 4: Server-generated ids, with a placeholder convention</h2>

<p>Building on Option 3: we didn’t want client-provided ids. Efficiency, security, and just not wanting two id-generation paths in the system all pointed the same direction.</p>

<p>So creation uses a temporary key with a reserved prefix <code class="language-plaintext highlighter-rouge">new_</code>. Any key matching that pattern is treated as “add this to the collection.” The server generates the real id and echoes the temporary key back as a <code class="language-plaintext highlighter-rouge">correlation-id</code>, so the client can map its local reference to what the server assigned.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">PATCH</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"a2"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"changed"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"new_1"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"four"</span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="err">//</span><span class="w"> </span><span class="err">response</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"items"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"a2"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"changed"</span><span class="p">},</span><span class="w">
    </span><span class="nl">"a4"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nl">"correlation-id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"new_1"</span><span class="p">,</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"four"</span><span class="p">}</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">correlation-id</code> only appears in the response to a patch that created something. It’s never stored, never returned on a plain <code class="language-plaintext highlighter-rouge">GET</code>. Its whole job is closing the loop between the client’s temporary key and the server’s real one, in the same request.</p>

<p>This is the option that ended up carrying the most weight in our own discussion, and where the team landed. One request, any mix of create, update, and delete, still a fully valid JSON Merge Patch. Nothing invented beyond a naming convention and one response-only field.</p>

<h2 id="option-5-model-it-as-its-own-sub-resource">Option 5: Model it as its own sub-resource</h2>

<p>Give the collection its own path. Nested under the parent, or, if the elements have real global identity, as its own top-level collection.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET /orders/{orderId}/items
POST /orders/{orderId}/items
GET /orders/{orderId}/items/{itemId}
PATCH /orders/{orderId}/items/{itemId}
DELETE /orders/{orderId}/items/{itemId}
</code></pre></div></div>

<p>This is the most honest modeling option if the elements genuinely have independent identity and lifecycle. It’s also the most disruptive to the existing contract, since you’re no longer patching the parent to change a child.</p>

<p>The deciding question is how your clients actually make changes. If a parent and its sub-collection tend to change together, and you want that to happen atomically in one request, Options 3 or 4 keep that possible and a separate sub-resource doesn’t. If changes to the sub-collection happen on their own, independent of the parent, giving it its own path is the more honest, RESTful choice.</p>

<h2 id="where-we-landed">Where we landed</h2>

<p>We didn’t pick one option and retire the rest, but we also don’t reach for all five with any regularity. Option 5 showed up when a sub-collection was sufficiently complex and deserves its own path. Option 2 and Option 3 stayed as discussion points rather than something we shipped.</p>

<p>Our default is Option 1 when nothing has independent identity, and Option 4 the moment something does and the server needs to own its id. The others are on this list because they’re real, useful tools for a shape of problem we haven’t hit yet, not because we’re using them in parallel across the API.</p>

<p>The mistake we were making before this discussion wasn’t picking the wrong option. It was never asking the question, and letting every array stay an array because that’s the shape it happened to arrive in.</p>

<p>If you’re stuck on the same problem, don’t look for the one correct answer. Look at what your collection actually is, then pick from here. And if you’ve found a sixth option, or a use case where one of ours falls apart, I’d very much like to hear about it.</p>

<hr />

<p><em>Title photo by <a href="https://unsplash.com/@leo_visions_">Leo_Visions</a>.</em></p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[We use RFC 7396 JSON Merge Patch across our public API. It's simple, it's well specified, and clients like it. JSON Merge Patch acts like a simple ‘diff’. The patch document mirrors the structure of the document you want to change. To add or update a field, you send the new value. To delete a field, you set the value to `null`. The rest stays as it was. Simple. Then we hit arrays.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_center,h_720,w_1280/v1786563565/leo_visions-cCNtRmBBMw8-unsplash_j7yzua.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_center,h_720,w_1280/v1786563565/leo_visions-cCNtRmBBMw8-unsplash_j7yzua.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">You hired them to speak up on day one</title><link href="https://robinpokorny.com/blog/you-hired-them-to-speak-up-on-day-one/" rel="alternate" type="text/html" title="You hired them to speak up on day one" /><published>2026-06-12T13:40:00+00:00</published><updated>2026-06-12T13:40:00+00:00</updated><id>https://robinpokorny.com/blog/you-hired-them-to-speak-up-on-day-one</id><content type="html" xml:base="https://robinpokorny.com/blog/you-hired-them-to-speak-up-on-day-one/"><![CDATA[<p>The newest person often sees the red flags first and says the least.</p>

<p>I joined a team that called itself empowered. Very quickly, I saw that almost every meaningful step still needed stakeholder approval, and each approval could turn into a veto later. I noticed the pattern early, but because I was new, I assumed I was missing context. That everyone else understood something I did not.</p>

<p>So I stayed quiet. Week after week went into aligning with stakeholders, reworking plans, keeping everyone happy. Nothing shipped to customers. When I hinted something felt off, the concern was easy to dismiss as newcomer impatience.</p>

<p>Soon after, the delays, vetoes, and confusion caught up with us. The team more or less fell apart.</p>

<h2 id="the-cost-of-staying-quiet">The cost of staying quiet</h2>

<p>I have since spoken to several people in similar situations. Almost all of them stayed quiet. Almost all of them regret it. Some shame themselves for it. They saw the signs, they wanted to speak, and in the moment some of them chickened out. Their words, not mine.</p>

<p>That silence is expensive.</p>

<p>It is easy to understand why it happens. You assume the others know something you do not. Your expertise feels like it does not quite apply yet. You tell yourself: observe first, get the full picture, then speak. There are real technical problems that need your attention right now. And sometimes you convince yourself it is about your relative seniority, or that you have not yet earned the standing to challenge how things work here. Sometimes that is even true.</p>

<p>We are good at rationalising away discomfort. That is not weakness; it is very human. I do not want to shame anyone for it.</p>

<p>But if you are reading this and recognising a moment where you stayed quiet and still think about it: do not beat yourself up too much. Use it. The fact that it still bothers you is a signal that your instincts were working. Next time you feel that pull, remember this. Practice is how you get there.</p>

<h2 id="what-you-are-actually-hiring-for">What you are actually hiring for</h2>

<p>The team welcoming a senior hire often expects something specific: more output capacity. Someone who brings deep expertise, ships things, and makes the existing work go faster. That expectation is reasonable. It is often part of what happens.</p>

<p>But the most experienced people, the ones who have seen many teams and contexts, often deliver something different and more valuable. They see things the team has stopped seeing. Through genuine fresh perspective and creativity, they can expand outcomes rather than just output. What was previously not even imagined becomes possible. And this applies to any role, not just engineering.</p>

<p>When someone arrives from outside and names something as very wrong, it can feel like the worst version of imposter syndrome coming true. Perhaps we were not as good as we thought. Perhaps the processes, the agreements, the way things actually get decided, were never quite right. That is a genuinely hard thing to sit with honestly.</p>

<p>What helps is to remind yourself: you hired them for this. Radical improvements sometimes need someone willing to say the thing that everyone else has rationalised away. That is not a sign of your failure. It is what good hiring looks like.</p>

<p>Do not expect the signal to come in the form you imagined. It probably will not be a technical observation. More often it will be about processes, about how decisions are made, about the social fabric of how you work together. The sociotechnical layer. The newcomer might feel strange raising it: ‘Why am I even talking about this? They hired me for technology.’ But processes and technology are parts of the same system.</p>

<p>Embrace that feedback. Evaluate it honestly. That is hard work, and it needs to stay anchored to what the team actually needs.</p>

<p>What makes these people valuable is not only their technical ability. It is their capacity to expand what the team believes is possible. That can feel uncomfortable. That is also exactly why they are worth hiring.</p>

<h2 id="if-you-are-the-new-one">If you are the new one</h2>

<p>Say it. Strong opinions, stated plainly, team success first. You can be wrong. You are probably right about some of it. And even when you are wrong, the team that handles that honestly is the team worth being part of.</p>

<h2 id="if-you-are-welcoming-someone">If you are welcoming someone</h2>

<p>Make it genuinely safe to raise uncomfortable things. When a newcomer names something that feels off, your first job is to listen. Be prepared to radically reëvaluate. They are not making waves. They are doing exactly what you needed when you hired them.</p>

<hr />

<p><em>Title photo by <a href="https://unsplash.com/@charlesdeluvio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">charlesdeluvio</a>.</em></p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[The newest person often sees the red flags first and says the least. I joined a team that called itself empowered. Very quickly, I saw that almost every meaningful step still needed stakeholder approval, and each approval could turn into a veto later. I noticed the pattern early, but because I was new, I assumed I was missing context. That everyone else understood something I did not.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/t_Thumb/v1781199884/charlesdeluvio-Lks7vei-eAg-unsplash_wtwjvg.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/t_Thumb/v1781199884/charlesdeluvio-Lks7vei-eAg-unsplash_wtwjvg.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Supermarket Meeting: The Secret to Cutting Down Useless Meetings</title><link href="https://robinpokorny.com/blog/supermarket-meeting-the-secret-to-cutting-down-useless-meetings/" rel="alternate" type="text/html" title="Supermarket Meeting: The Secret to Cutting Down Useless Meetings" /><published>2024-09-12T09:34:00+00:00</published><updated>2024-09-12T09:34:00+00:00</updated><id>https://robinpokorny.com/blog/supermarket-meeting-the-secret-to-cutting-down-useless-meetings</id><content type="html" xml:base="https://robinpokorny.com/blog/supermarket-meeting-the-secret-to-cutting-down-useless-meetings/"><![CDATA[<p>Meetings. Whoever you are, I’m sure this word brings an emotional response.</p>

<p>Maybe you see them as a way to reach agreement, maybe you hate them with a passion, maybe you view them as a necessary evil. Maybe you even see them as a welcome break in your workday, maybe you think your reports see them like a welcome break.</p>

<p>Over the years, I’ve experienced meetings across the entire spectrum of quality, usefulness, and engagement. Some of my career bests have happened in meetings, and so have some of my worst moments.</p>

<p>The main rule I’ve developed for meetings is simple: <strong>When you’re there, be present.</strong></p>

<p>That means no browsing, no Slack, no coding while the meeting lasts. If the meeting is bad, you have three options: actively make it better, call it out, or just leave. But when I’m there, I want to use the time as effectively as possible.</p>

<h2 id="the-supermarket-over-the-specialized-shop">The Supermarket Over the Specialized Shop</h2>

<p>When I plan my week or day, I want meetings to use the time they’re scheduled for—not more, not less. I dislike going overtime just as much as I dislike when the host suddenly ‘gives me 20 minutes back.’ On the same note, it’s annoying to receive a cancellation email for lack of topics just an hour before the start of a weekly meeting.</p>

<p>So when someone suggested a new meeting for a quite specific topic, I shared my concerns. Maybe it would work for the first two three sessions, but eventually, the topics would dry up, and the meeting would die out. Keeping a recurring meeting alive and interesting requires—surprisingly—a lot of work.</p>

<p>Then I realized we already have some recurring meetings that sometimes end sooner and sometimes get cancelled. It would be much better to expand their purpose to allow related topics. This way, we ensure that the allocated time gets fully used before starting anything new. By making meetings more saturated with diverse topics, we maximize their value.</p>

<blockquote>
  <p><em>A <strong>Supermarket Meeting</strong> is a consolidated approach to recurring meetings, where diverse topics are discussed in one weekly session, similar to how you’d buy various items in one trip to the supermarket. Instead of creating multiple specialized meetings for different subjects, a supermarket meeting gathers all related discussions into a single, regular time slot. This maximizes productivity, ensures efficient use of time, and keeps meetings engaging and relevant.</em></p>
</blockquote>

<p>It’s like a supermarket visit where you buy all your groceries at once, instead of going to specialized shops—baker’s on Mondays, butcher’s on Tuesdays, and a wine shop on Fridays. One meeting, every week, same time, diverse topics.</p>

<h2 id="a-new-approach-to-meetings">A New Approach to Meetings</h2>

<p>From now on, I plan to use a single weekly meeting as a “supermarket” for discussing anything relevant to Tech. A GraphQL schema question? Bring it on! Kafka learnings from your previous job? Sure! DataDog feeding itself quirk? Our inner geeks love that!</p>

<p>Then, if (or should I write iff?) we often find we don’t have enough time to cover everything, or that some areas would benefit from their own meeting, we’ll create a new slot.</p>

<p>I’m sure this approach will lead to more engaging meetings while adding some predictability to our schedules. Win, win.</p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[A Supermarket Meeting is a consolidated approach to recurring meetings, where diverse topics are discussed in one weekly session, similar to how you’d buy various items in one trip to the supermarket. Instead of creating multiple specialized meetings for different subjects, a supermarket meeting gathers all related discussions into a single, regular time slot. This maximizes productivity, ensures efficient use of time, and keeps meetings engaging and relevant.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,w_1280,h_720/v1726133085/Motivational_Quotes_Blog_Banner_bgzrm5.png" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,w_1280,h_720/v1726133085/Motivational_Quotes_Blog_Banner_bgzrm5.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">3 Mistakes That Give Microservices a Bad Name</title><link href="https://robinpokorny.com/blog/3-mistakes-that-give-microservices-a-bad-name/" rel="alternate" type="text/html" title="3 Mistakes That Give Microservices a Bad Name" /><published>2023-11-09T09:05:03+00:00</published><updated>2023-11-09T09:05:03+00:00</updated><id>https://robinpokorny.com/blog/3-mistakes-that-give-microservices-a-bad-name</id><content type="html" xml:base="https://robinpokorny.com/blog/3-mistakes-that-give-microservices-a-bad-name/"><![CDATA[<p>I’m sad to see that microservices are falling in popularity among architects and developers.</p>

<p>Some say they are  <a href="https://metyis.com/impact/our-insights/is-over-engineering-always-the-best-approach">unnecessarily complex or overengineered</a>. That one needs to learn so  <a href="https://landscape.cncf.io/">many new tools and technologies</a>. That they introduce  <a href="https://stackoverflow.blog/2020/11/23/the-macro-problem-with-microservices/">problems we had already solved</a>.</p>

<p>However, many ‘do microservices’ (unintentionally) wrong, mimicking the external displays without harvesting the benefits. I’d say that thinking in microservices is the most useful design approach we’ve created as an industry and every software architect should adopt it.</p>

<p>Here I list 3 mistakes I often see that make some people dislike microservices.</p>

<h2 id="mistake-1-confusing-microservices-with-distributed-systems">Mistake 1: Confusing Microservices with Distributed Systems</h2>

<p>When you chop your application into multiple servers/containers/lambdas, you haven’t created microservices.</p>

<p>Microservices require a lot of thinking about what logic should be together and what logic should be separate. The resulting areas form so-called Bounded Contexts (a term from DDD) that allow you to independently model that area’s problem. In each area, the same word (like User) has a different meaning so you need to be careful about translating from one context to another.</p>

<p>There is a lot of benefit in keeping these areas isolated and protected in a distributed system, so you bear with the increased complexity. Do not add complexity without that benefit.</p>

<h2 id="mistake-2-independent-deployability-over-design-time-decoupling">Mistake 2: Independent Deployability over Design-Time Decoupling</h2>

<p>It’s nice and efficient when you can make a production change in one service without deploying other services.</p>

<p>But if that change required synchronisation with other team(s) during development then only the last bit was efficient. I’m sure most developers would trade meetings and Slack messages with some difficulties during deployment any day of the week. There is a huge compounding payoff every time a team is free to develop features without hard dependencies.</p>

<p>Decoupling modules during design will help you make those modules independently deployable later; it doesn’t work the other way around.</p>

<h2 id="mistake-3-unnecessarily-small-microservices">Mistake 3: Unnecessarily Small Microservices</h2>

<p>I think that the ‘micro’ in the name can mislead developers to create too many, too small microservices.</p>

<p>First, ‘micro’ does not mean the same as ‘atomic’: a piece of logic does not need its own service whenever you can draw some line around it. Second, let’s focus more on the final part: ‘service’. There should be enough functionality in a microservice that it would provide some useful, well, service. In my opinion, any need for distributed transactions is a strong indicator of too small microservices.</p>

<p>No simple rule (200 LOC, rewrite in two weeks, and even more reasonable ones like one-microservice-per-team) can replace a good, deep analysis of your system.</p>

<p>When you apply the microservices thinking and simultaneously avoid these mistakes you might come to the conclusion that your system needs only one microservice for now. That is fine and quite common. And yes, you end up with a ‘monolith’. Yet, you applied a powerful technique you can keep reusing. It was not a decision based on the fixed mindset of two competing patterns. Congrats.</p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[I'm sad to see that microservices are falling in popularity among architects and developers. Some say they are unnecessarily complex or overengineered. That one needs to learn so many new tools and technologies. That they introduce problems we had already solved. However, many ‘do microservices’ (unintentionally) wrong…]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_scale,f_auto,w_1280/v1699522096/Blue_and_Red_Motivational_Quotes_Blog_Banner_wjq6br.png" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_scale,f_auto,w_1280/v1699522096/Blue_and_Red_Motivational_Quotes_Blog_Banner_wjq6br.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Why Developers Should Stop Using ISO 8601 for Date-Time</title><link href="https://robinpokorny.com/blog/why-developers-should-stop-using-iso-8601-for-date-time/" rel="alternate" type="text/html" title="Why Developers Should Stop Using ISO 8601 for Date-Time" /><published>2023-08-07T15:02:15+00:00</published><updated>2023-08-07T15:02:15+00:00</updated><id>https://robinpokorny.com/blog/why-developers-should-stop-using-iso-8601-for-date-time</id><content type="html" xml:base="https://robinpokorny.com/blog/why-developers-should-stop-using-iso-8601-for-date-time/"><![CDATA[<p>When documenting APIs, developers often link to <strong>ISO 8601</strong> as the standard for computer-readable date and date-time format.</p>

<p>Dates and times (and time zones!) are complicated. There are so many edge cases and pitfalls. I’m sure every developer has a battle story about them. It’s good to delegate that hard work to somebody else. So when an international body that everybody knows and trusts publishes such a standard, it’s no surprise all the API designers start referring to it.</p>

<p>This is what an <strong>ISO 8601</strong> date and date-times look like:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">2023‐08‐07</code></li>
  <li><code class="language-plaintext highlighter-rouge">2023‐08‐07T13:25:38Z</code></li>
</ul>

<p>This is what we want to receive.</p>

<h3 id="the-iso-allows-too-much-variability-and-its-paid-to-read">The ISO allows too much variability and it’s paid to read</h3>

<p>Do you know what is also a valid <strong>ISO 8601</strong> date-time?</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">2023-W32-1T15:38+02:00</code> (= Monday of the 32nd week in my local time zone)</li>
</ul>

<p>How sure are you that your API will accept such a string? For example, JavaScript’s <code class="language-plaintext highlighter-rouge">Date.parse</code> will fail. There are many more allowed formats in the standard. And support for these is not guaranteed at all.</p>

<p>If you are thinking about creating a library that will understand all of them, I have bad news for you. There are four versions of the standard, released in the years 1988, 2000, 2004, and 2019, and they are not fully compatible with each other! Plus, you need to pay (about $190) to receive a copy of the standard.</p>

<p>Fortunately, there is a better way:</p>

<h3 id="there-are-two-better-suited-and-free-standards"><strong>There are two better-suited (and free) standards</strong></h3>

<p>In your documentation, refer to either of these two standards:</p>

<ul>
  <li><strong>RFC 3339</strong></li>
  <li><strong>HTML</strong> (who would’ve guessed?)</li>
</ul>

<p>Each of those allows just a small variation of that date-time we want: allowing space instead of <code class="language-plaintext highlighter-rouge">T</code> or not providing some parts. To my knowledge, all of those variations are generally supported. Moreover, the standards are precise and free to read for anybody.</p>

<p>If you want to be truly strict, I’d also include the format like so:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">RFC3339 date-time in %Y-%M-%DT%h:%m:%sZ format</code></li>
</ul>

<p>This is a very clear way to document your API.</p>

<h3 id="next-time-just-write-rfc-3339-instead"><strong>Next time, just write RFC 3339 instead</strong></h3>

<p>When you find yourself typing ISO 8601 in your code or documentation, just replace it with RFC 3339 and continue knowing you made dates a tiny bit easier for you and your API users.</p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[When documenting APIs, developers often link to ISO 8601 as the standard for computer-readable date and date-time format. Dates and times (and time zones!) are complicated. There are so many edge cases and pitfalls. I’m sure every developer has a battle story about them. It’s good to delegate that hard work to somebody else. So when an international body that everybody knows and trusts publishes such a standard, it’s no surprise all the API designers start referring to it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_south,h_720,w_1280/v1691421054/kyrie-kim-jqxB3C0YNG0-unsplash_qkjqoe.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_south,h_720,w_1280/v1691421054/kyrie-kim-jqxB3C0YNG0-unsplash_qkjqoe.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Replace null with ES6 Symbols</title><link href="https://robinpokorny.com/blog/replace-null-with-es6-symbols/" rel="alternate" type="text/html" title="Replace null with ES6 Symbols" /><published>2021-07-24T12:27:01+00:00</published><updated>2021-07-24T12:27:01+00:00</updated><id>https://robinpokorny.com/blog/replace-null-with-es6-symbols</id><content type="html" xml:base="https://robinpokorny.com/blog/replace-null-with-es6-symbols/"><![CDATA[<p>When I was working on my small side-project library, I needed to represent a missing value. In the past, I’d used the nullable approach in simple settings and Option (aka Maybe) when I wanted more control.</p>

<p>In this case, neither felt correct so I came up with a different approach I’d like to present.</p>

<h2 id="why-nullable-was-not-enough">Why Nullable was not enough</h2>

<p>Nullable means that when there is a value it is a string, a number, or an object. When there is no value, we use either <code class="language-plaintext highlighter-rouge">null</code> or <code class="language-plaintext highlighter-rouge">undefined</code>.</p>

<p><em>Tip:</em> if you work with nullable types in TypeScript, make sure you turn on the <a href="https://www.typescriptlang.org/tsconfig#strictNullChecks"><code class="language-plaintext highlighter-rouge">strictNullChecks</code></a></p>

<p>This is often fine.</p>

<p>There are, in general, two cases when it’s not:</p>

<ol>
  <li>The value <em>can</em> be <code class="language-plaintext highlighter-rouge">null</code> or <code class="language-plaintext highlighter-rouge">undefined</code>. In the end, these are both valid JavaScript primitives and people can use them in many ways.</li>
  <li>You want to add some advanced logic. Writing <code class="language-plaintext highlighter-rouge">x == null</code> everywhere gets cumbersome.</li>
</ol>

<p>In my case I was handling an output of a Promise, that can return
anything. And I could foresee that both of the ‘missing’ will be eventually returned.</p>

<p>In general, the problem 1 and 2 have the same solution: use a library that implements the Option type.</p>

<h2 id="why-option-was-too-much">Why Option was too much</h2>

<p>Option (sometimes called Maybe) type has two possibilities: either there is no value (<code class="language-plaintext highlighter-rouge">None</code> on <code class="language-plaintext highlighter-rouge">Nothing</code>) or there is a value (<code class="language-plaintext highlighter-rouge">Some</code> or <code class="language-plaintext highlighter-rouge">Just</code>).</p>

<p>In JavaScript/TypeScript this means introducing a new structure that wraps the value. Most commonly an object with a property <code class="language-plaintext highlighter-rouge">tag</code> that defines what possibility it is.</p>

<p>This is how you could quickly implement Option in TypeScript:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Option</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span> <span class="o">=</span> <span class="p">{</span> <span class="na">tag</span><span class="p">:</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span> <span class="p">}</span> <span class="o">|</span> <span class="p">{</span> <span class="na">tag</span><span class="p">:</span> <span class="dl">'</span><span class="s1">some</span><span class="dl">'</span><span class="p">,</span> <span class="na">value</span><span class="p">:</span> <span class="nx">T</span> <span class="p">}</span>
</code></pre></div></div>

<p>Usually, you would use a library that defines the type and a bunch of useful utils alongside. <a href="https://dev.to/ryanleecode/practical-guide-to-fp-ts-option-map-flatten-chain-6d5">Here is an intro to Option in my favourite fp-ts library</a>.</p>

<p>The library I was building was small, had zero dependencies, and there was no need for using any Option utility. Therefore, bringing in an Option library would be overkill.</p>

<p><a href="https://github.com/robinpokorny/promise-throttle-all"><img src="https://opengraph.githubassets.com/780e6396675570ae972817e780369a919b4ef3917614832dab09d4728d451283/robinpokorny/promise-throttle-all" alt="" /></a></p>

<p>For a while I was thinking about inlining the Option, that is coding it from scratch. For my use case that would be just a few lines. It would complicate the logic of the library a bit, though.</p>

<p>Then, I had a better idea!</p>

<h2 id="symbol-as-the-new-null">Symbol as the new null</h2>

<p>Coming back to Nullable, the unsolvable problem is that <code class="language-plaintext highlighter-rouge">null</code> (or <code class="language-plaintext highlighter-rouge">undefined</code>) is global. It is one value equal to itself. It is the same for everybody.</p>

<p>If you return <code class="language-plaintext highlighter-rouge">null</code> and I return <code class="language-plaintext highlighter-rouge">null</code>, later, it is not possible to find out where the <code class="language-plaintext highlighter-rouge">null</code> comes from.</p>

<p>In other words, there is ever only one instance. To solve it, we need to have a new instance of <code class="language-plaintext highlighter-rouge">null</code>.</p>

<p>Sure, we could use an empty object. In JavaScript each object is a new instance that is not equal to any other object.</p>

<p>But hey, in ES6 we got a new primitive that does exactly that: Symbol. (Read some <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-symbols/">introduction to Symbols</a>)</p>

<p>What I did was a new constant that represented a missing value, which was a symbol:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">None</span> <span class="o">=</span> <span class="nc">Symbol</span><span class="p">(</span><span class="s2">`None`</span><span class="p">)</span>
</code></pre></div></div>

<p>Let’s look at the benefits:</p>

<ul>
  <li>It is a simple value, no wrapper needed</li>
  <li>Anything else is treated as data</li>
  <li>It’s a private None, the symbol cannot be recreated elsewhere</li>
  <li>It has no meaning outside our code</li>
  <li>The label makes debugging easier</li>
</ul>

<p>That is great! Especially the first point allows using None as <code class="language-plaintext highlighter-rouge">null</code>. See some example use:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">isNone</span> <span class="o">=</span> <span class="p">(</span><span class="nx">value</span><span class="p">:</span> <span class="nx">unknown</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">x</span> <span class="o">===</span> <span class="nx">None</span>

<span class="kd">const</span> <span class="nx">hasNone</span> <span class="o">=</span> <span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o">&lt;</span><span class="nx">unknown</span><span class="o">&gt;</span><span class="p">)</span> <span class="o">=&gt;</span>
  <span class="nx">arr</span><span class="p">.</span><span class="nf">some</span><span class="p">((</span><span class="nx">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">x</span> <span class="o">===</span> <span class="nx">None</span><span class="p">)</span>

<span class="kd">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span> <span class="nx">S</span><span class="o">&gt;</span><span class="p">(</span>
  <span class="nx">fn</span><span class="p">:</span> <span class="p">(</span><span class="nx">x</span><span class="p">:</span> <span class="nx">T</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">S</span><span class="p">,</span>
  <span class="nx">value</span><span class="p">:</span> <span class="nx">T</span> <span class="o">|</span> <span class="k">typeof</span> <span class="nx">None</span>
<span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="k">if </span><span class="p">(</span><span class="nx">value</span> <span class="o">===</span> <span class="nx">None</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">None</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nf">fn</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="symbols-are-almost-nulls">Symbols are almost nulls</h2>

<p>There are some disadvantages, too.</p>

<p>First, which is IMO rare, is that the environment has to <a href="https://caniuse.com/mdn-javascript_builtins_symbol">support ES6 Symbols</a>. That means Node.js &gt;=0.12 (not to be confused with v12).</p>

<p>Second, there are problems with (de)serialisation. Funnily, Symbols behave exactly like <code class="language-plaintext highlighter-rouge">undefined</code>.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">JSON</span><span class="p">.</span><span class="nf">stringify</span><span class="p">({</span> <span class="na">x</span><span class="p">:</span> <span class="nc">Symbol</span><span class="p">(),</span> <span class="na">y</span><span class="p">:</span> <span class="kc">undefined</span> <span class="p">})</span>
<span class="c1">// -&gt; "{}"</span>

<span class="nx">JSON</span><span class="p">.</span><span class="nf">stringify</span><span class="p">([</span><span class="nc">Symbol</span><span class="p">(),</span> <span class="kc">undefined</span><span class="p">])</span>
<span class="c1">// -&gt; "[null,null]"</span>
</code></pre></div></div>

<p>So, the information about the instance is, of course, lost. Yet, since it then behaves like <code class="language-plaintext highlighter-rouge">undefined</code>—the native ‘missing value’)—makes it well suited for representing a custom ‘missing value’.</p>

<p>In contrast, Option is based on structure not instances. Any object with a property <code class="language-plaintext highlighter-rouge">tag</code> set to <code class="language-plaintext highlighter-rouge">none</code> is considered None. This allows for easier serialisation and deserialisation.</p>

<h2 id="summary">Summary</h2>

<p>I’m rather happy with this pattern. It seems it’s a safer alternative to <code class="language-plaintext highlighter-rouge">null</code> in places where no advanced operations on the property are needed.</p>

<p>Maybe, I’d avoid it if this custom symbol should leak outside of a module or a library.</p>

<p>I especially like that with the variable name and the symbol label, I can communicate the domain meaning of the missing value. In my small library it represents that the promise is not settled:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">notSettled</span> <span class="o">=</span> <span class="nc">Symbol</span><span class="p">(</span><span class="s2">`not-settled`</span><span class="p">)</span>
</code></pre></div></div>

<p>Potentially, there could be multiple missing values for different domain meanings.</p>

<blockquote>
  <p>Let me know what you think of this use? Is it a good replacement for <code class="language-plaintext highlighter-rouge">null</code>? Should everybody always use an Option?</p>
</blockquote>

<p>Note: Symbols are not always easy to use, watch my talk <em>Symbols complicated it all</em>.</p>

<p><a href="https://youtu.be/YrQ_ecirpDA"><img src="https://res.cloudinary.com/dljslvfla/image/upload/v1627129515/Screenshot_2021-07-24_at_14.23.13_bvsphx.png" alt="" /></a></p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[When I was working on my small side-project library, I needed to represent a missing value. In the past, I'd used the nullable approach in simple settings and Option (aka Maybe) when I wanted more control. In this case neither felt correct so I came up with a different approach I'd like to present.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_scale,f_auto,w_1280/v1627128971/Blue_and_Red_Motivational_Quotes_Blog_Banner_tirkqv.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_scale,f_auto,w_1280/v1627128971/Blue_and_Red_Motivational_Quotes_Blog_Banner_tirkqv.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Dictator paradox: Why micromanagement is so tempting</title><link href="https://robinpokorny.com/blog/dictator-paradox-why-micromanagement-is-so-tempting/" rel="alternate" type="text/html" title="Dictator paradox: Why micromanagement is so tempting" /><published>2021-05-25T21:18:04+00:00</published><updated>2021-05-25T21:18:04+00:00</updated><id>https://robinpokorny.com/blog/dictator-paradox-why-micromanagement-is-so-tempting</id><content type="html" xml:base="https://robinpokorny.com/blog/dictator-paradox-why-micromanagement-is-so-tempting/"><![CDATA[<p>I firmly believe all creative people hate when others tell them what to do. When instead of problems to solve, they are handled solutions to implement or, even worse, isolated tasks to just complete.</p>

<p>Yet, the world is full of micromanagers.</p>

<p>Over my career, I’ve heard countless complaints about how managers do not give their reports enough context, enough trust, enough freedom. That they decide all on their own.</p>

<p>Why is that?</p>

<p><strong>Because micromanagement gets the thing done faster.</strong></p>

<p>Well, kind of. Let me explain.</p>

<h3 id="dictators-and-complex-systems">Dictators and complex systems</h3>

<p>Originally a <a href="https://en.wikipedia.org/wiki/Roman_dictator">dictator</a> (a micromanager is a local dictator) was a role in Ancient Rome, giving almost unlimited power to a selected individual during wartime. The appointment was for emergencies only and it was time-limited.</p>

<p>The idea was that one person would hold all the important information in their head and, because of that, they will make educated decisions fast. And during the war, a good decision today trumps a better decision tomorrow.</p>

<p>Having a dictator was actually very smart.</p>

<p>At wartime.</p>

<p>You see, a war (or a company, or a software system) is an example of a complex <a href="https://www.goodreads.com/book/show/42360533-thinking-in-systems">system</a>. One crucial property of a complex system is that nobody can have a mental model of it that is complete.</p>

<p>That is, there were things (probably loads of things) that the Roman dictator did not count with and which harmed the people later. But, again, during the war, all is sacrificed towards winning it. Obviously, losing the war would harm all the citizens much more.</p>

<p>In other words, <strong>a dictator is a reasonable solution if fixing a single problem is all that matters</strong>. A dictator heavily favors a short-term solution over a long-term solution.</p>

<p>That is never the case in the real world of software engineering. While there are strict deadlines, meeting them with an exhausted team that is unable to continue is not acceptable. Neither is sacrificing the quality and maintainability of the architecture.</p>

<p>The project you are working on, however important it seems, cannot jeopardize the ability of the team to continue tackling the next projects. This includes piling the technical debt.</p>

<h3 id="why-is-that-a-paradox">Why is that a paradox?</h3>

<p>What I write might seem clear and obvious (I hope it is!). So, where is the paradox?</p>

<p>I define the <strong>Dictator paradox</strong> as the following:</p>

<blockquote>
  <p><strong>Given a set of projects, every single project alone will be finished faster with a dictator. However, to finish all of the projects, decentralization and coöperation will beat any dictator.</strong></p>
</blockquote>

<p>This is the reason why people talk about self-organized teams, incremental delivery, and emergent design.</p>

<p>This is why the industry has replaced Waterfall with Agile development.</p>

<p>This is also why when the pressure makes a manager forget the context and perspective, they will start to micromanage.</p>

<p>After all: <em>A dictator is a reasonable solution if fixing a single problem is all that matters.</em></p>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[I firmly believe all creative people hate when others tell them what to do. When instead of problems to solve they are handled solutions to implement or, even worse, isolated tasks to just complete. Yet, the world is full of micromanagers. Over my career, I’ve heard countless complaints about how managers do not give their reports enough context, enough trust, enough freedom. That they decide all on their own. Why is that?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_north,h_1080,w_1920/v1621977139/cristina-gottardi-05P65mxLuW8-unsplash_fcw8jr.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_north,h_1080,w_1920/v1621977139/cristina-gottardi-05P65mxLuW8-unsplash_fcw8jr.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">TypeScript Enums I Want to Actually Use</title><link href="https://robinpokorny.com/blog/typescript-enums-i-want-to-actually-use/" rel="alternate" type="text/html" title="TypeScript Enums I Want to Actually Use" /><published>2021-04-18T19:50:45+00:00</published><updated>2021-04-18T19:50:45+00:00</updated><id>https://robinpokorny.com/blog/typescript-enums-i-want-to-actually-use</id><content type="html" xml:base="https://robinpokorny.com/blog/typescript-enums-i-want-to-actually-use/"><![CDATA[<p>Since the very first moment I learned about TypeScript, I knew there’s gonna be this one thing I’ll always hate: <em>Enums</em>. So un-elegant, so old-school, and so why-do-you-pollute-my-runtime.</p>

<p>Well, I was wrong. I use Enums now. At least some of them.</p>

<p>Let me show you.</p>

<h2 id="what-is-an-enum-in-typescript">What is an Enum in TypeScript</h2>

<p>First, let’s quickly talk about what are Enumerators, or Enums for short.</p>

<p>An Enum in TypeScript is <strong>a well-defined collection of a limited number of cases</strong>. That is, we write down all possibilities and do not allow anything else.</p>

<p>The meaning of enumerations is that in the code you deal with only these few cases and you can be sure to deal with all of them. The compiler will warn if you forget to handle one or more.</p>

<p>Here are some common enumeration examples to give you a better idea:</p>

<ul>
  <li>Directions: <code class="language-plaintext highlighter-rouge">North</code>, <code class="language-plaintext highlighter-rouge">South</code>, <code class="language-plaintext highlighter-rouge">East</code>, <code class="language-plaintext highlighter-rouge">West</code></li>
  <li>CardRanks: <code class="language-plaintext highlighter-rouge">Ace</code>, <code class="language-plaintext highlighter-rouge">King</code>, <code class="language-plaintext highlighter-rouge">Queen</code>, <code class="language-plaintext highlighter-rouge">Jack</code>, <code class="language-plaintext highlighter-rouge">10</code>, <code class="language-plaintext highlighter-rouge">9</code>, <code class="language-plaintext highlighter-rouge">8</code>, <code class="language-plaintext highlighter-rouge">7</code>, <code class="language-plaintext highlighter-rouge">6</code>, <code class="language-plaintext highlighter-rouge">5</code>, <code class="language-plaintext highlighter-rouge">4</code>, <code class="language-plaintext highlighter-rouge">3</code>, <code class="language-plaintext highlighter-rouge">2</code></li>
  <li>DateFormats: <code class="language-plaintext highlighter-rouge">Unix</code>, <code class="language-plaintext highlighter-rouge">ISO</code>, <code class="language-plaintext highlighter-rouge">Email</code></li>
</ul>

<p>In this article, I’ll be using countries my app supports as an example. This is how you write enums in TypeScript:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">enum</span> <span class="nx">Country</span> <span class="p">{</span>
  <span class="nx">Germany</span><span class="p">,</span>
  <span class="nx">Sweden</span><span class="p">,</span>
  <span class="nx">USA</span><span class="p">,</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It is almost like a simple object. Notice that there is no equal sign, this is not an assignment. The definition looks similar to the definition of an interface.</p>

<p>There is one interesting property of an Enum: it defines both types and values. See some use here:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">enum</span> <span class="nx">Country</span> <span class="p">{</span>
  <span class="nx">Germany</span><span class="p">,</span>
  <span class="nx">Sweden</span><span class="p">,</span>
  <span class="nx">USA</span><span class="p">,</span>
<span class="p">}</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">//                               ^^^ this is a type</span>
  
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">Country</span><span class="p">.</span><span class="nx">Sweden</span><span class="p">)</span>
<span class="c1">//               ^^^ this is a value</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?#code/KYOwrgtgBAwg9mEAXATgTygbwFBSgcWBQgEMQ0AaXKAZQHdgATUKvAVRoEEqBfavAYLzYAxnBABnJFAnAknEUgCWAN2DxEqDAF4oACjGb0ALlgJk6AJRRtAPizUA9I6Gu37oQD1vUJAAslCShAqBJfNAAHYGonF0Y4GTgIOQCQAHNsPmxZeUVVdXMtPQ0LNAA6eiZQS1iPQW9PXwCgkLCVEgAbMGjsZygAASQJAFpgAA8oxVGUFDgUbLkFZTUSooByGgBRNcsgA">Playground Link</a></p>

<blockquote>
  <p><em>Note</em>: I use <code class="language-plaintext highlighter-rouge">@ts-expect-error</code> in the code examples to mark there is a TypeScript error on the next line. This also suppresses the error, so you will not see it in the playground. Remove the line to see the error reported.</p>
</blockquote>

<h2 id="whats-wrong-with-enums">What’s wrong with Enums</h2>

<p>Right, that sounds kind of nice, what is the problem?</p>

<p>There are three main points, I’ve held against Enums since day one.</p>

<h3 id="1-enums-introduce-ugly-runtime-code">1. Enums introduce (ugly) runtime code</h3>

<p>If you want to have a value available, it means that the value has to be there during runtime. That means Enums are one of the very few (and probably the only regularly used) TypeScript constructs that generate some code in the resulting JavaScript.</p>

<p>Usually, when the target is the current ECMAScript, all type definitions and annotations are just removed. That is because all other constructs like object literals, functions, or classes are the same in JavaScript as in TypeScript.</p>

<p>Look at how the <code class="language-plaintext highlighter-rouge">Country</code> Enum, defined above, ends up as:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Country</span><span class="p">;</span>
<span class="p">(</span><span class="nf">function </span><span class="p">(</span><span class="nx">Country</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">Country</span><span class="p">[</span><span class="nx">Country</span><span class="p">[</span><span class="dl">"</span><span class="s2">Germany</span><span class="dl">"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Germany</span><span class="dl">"</span><span class="p">;</span>
    <span class="nx">Country</span><span class="p">[</span><span class="nx">Country</span><span class="p">[</span><span class="dl">"</span><span class="s2">Sweden</span><span class="dl">"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Sweden</span><span class="dl">"</span><span class="p">;</span>
    <span class="nx">Country</span><span class="p">[</span><span class="nx">Country</span><span class="p">[</span><span class="dl">"</span><span class="s2">USA</span><span class="dl">"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">USA</span><span class="dl">"</span><span class="p">;</span>
<span class="p">})(</span><span class="nx">Country</span> <span class="o">||</span> <span class="p">(</span><span class="nx">Country</span> <span class="o">=</span> <span class="p">{}));</span>
</code></pre></div></div>

<h3 id="2-enums-are-number-based-by-default">2. Enums are number-based by default</h3>

<p>Do you see that code? Do you see those numbers 0, 1, and 2?</p>

<p>That is the actual value assigned to the country. So while you work with nice names, they are translated to numbers.</p>

<p>The generated code is practically equal to the following dictionary object.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">Country</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">Germany</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
  <span class="na">Sweden</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
  <span class="na">USA</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="p">};</span>
</code></pre></div></div>

<p>So when you want to debug your code and you log the country your function received, you get a cryptic number. Then you need to go and see the relevant version of the source code in TypeScript, count that number from the top, and then you have the name you actually wanted in the first place. Ugh, that is bad.</p>

<p>Another problem is that you can pass a number where <code class="language-plaintext highlighter-rouge">Country</code> type is expected. A maintenance headache about to happen on its own. But, you can actually pass <em>any</em> number, irrespective if it is defined in the Enum or not. Both of these calls <a href="https://www.typescriptlang.org/play?target=99&amp;strict=true#code/KYOwrgtgBAwg9mEAXATgTygbwFBSgcWBQgEMQ0AaXKAZQHdgATUKvAVRoEEqBfbbAMZwQAZyRQRwJJwFIAlgDdg8RKgwBeKAAohq9AC5YCZOgCUUdQD4s1APS2ojOBLgQpACzkgA5tj7ZJaVlFZWM1LQBGUwCpGXklFRM0SIAGFNMgA">will pass the type check</a>:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">setActiveCountry</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>   <span class="c1">// 1 for Sweden</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> <span class="c1">// 100 for ???</span>
</code></pre></div></div>

<p>Sure, an Enum should be just a unique value. And the developer should not care about the runtime value and treat the Enum as opaque. However, the whole translation to numbers feels very old-school, a reminder of times where memory was expensive and numbers were used as a means of saving it.</p>

<p>I know there is a solution with string Enums (we will talk about them in a bit). Yet, I do not understand why the values could not be equal to the labels which are unique already. Or, when the target is ES2015+, the values could be Symbols – using them at a place they were created for.</p>

<h3 id="3-enums-are-not-needed-in-typescript">3. Enums are not needed in TypeScript</h3>

<p>Do you have to use Enums in TypeScript?</p>

<p>No, there are other ways to type a limited number of cases.</p>

<p>I see people avoiding Enums in many ways. Either on purpose or out of habit. And, of course, you do not <em>need</em> them to write good code.</p>

<p>Before I show you how I’m using Enums now so that I’m comfortable with them, let’s explore these common alternatives and discuss their pros and cons.</p>

<h2 id="alternatives-to-enums">Alternatives to Enums</h2>

<h3 id="disjoint-union-of-literal-types">Disjoint union of literal types</h3>

<p>A rather straightforward option is to define a type that consists of all the actual strings (or other values) that are permitted. This is called disjoint or discriminated union; see <a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions">Discriminated Unions</a> in TypeScript docs.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Country</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">DE</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">US</span><span class="dl">'</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">CZ</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gVwHbAE4igXigcgCICiOUAPrgMpGm4Cq5OAUFMy6ywwMZxIDOwUPCMACCHYAEsAbhHjI0GbAAouc9AC5YiFOgCUWAHxQA3kygB6M1AAmcAXAC2QgBbikAcwYBfBg0EixUjJa8oo4lDg6PhZQAALAPAC0EAAekGJJqKhwqL5CohLSstogoTAAWhFAA">Playground Link</a></p>

<p>As you can see this approach correctly types the function. The problem is that there are ‘magic’ strings all over the place. Sure, for my example the strings are actually somewhat self-explanatory. But let’s imagine that instead of <a href="https://en.wikipedia.org/wiki/ISO_3166-1">ISO 3166-1</a> two-letter country codes we would be using <a href="https://en.wikipedia.org/wiki/ISO_3166-1_numeric">ISO 3166-1 numeric</a> country codes:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">type</span> <span class="nx">Country</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">276</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">752</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">840</span><span class="dl">'</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">752</span><span class="dl">'</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">203</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gVwHbAE4igXigcgEwDsAbDlAD64ECsepFOAHACwAMOAUFF9z9+wMZwkAZ2BRhEYAEF+wAJYA3CPGRoM2ABSDV6AFyxEKdAEosAPigBvTlAD0tqABM44uAFtJACzlIA5uwBfdnYJaVlFZUM1DRxqWmNg+ygAAWBhAFoIAA9IWUzUVDhUEMkZeSUVIxAYvBYAZhxjIA">Playground Link</a></p>

<p>While technically equivalent to the previous, this is now utterly unreadable and error-prone.</p>

<h3 id="disjoint-union-of-literal-types-with-constants">Disjoint union of literal types with constants</h3>

<p>What can we do to remove those ‘magic’ strings? Let’s save the values to constants:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">GERMANY</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">276</span><span class="dl">'</span>
<span class="kd">const</span> <span class="nx">SWEDEN</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">752</span><span class="dl">'</span>
<span class="kd">const</span> <span class="nx">USA</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">840</span><span class="dl">'</span>
<span class="kd">const</span> <span class="nx">CZECHIA</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">203</span><span class="dl">'</span>

<span class="kd">type</span> <span class="nx">Country</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">276</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">752</span><span class="dl">'</span> <span class="o">|</span> <span class="dl">'</span><span class="s1">840</span><span class="dl">'</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">SWEDEN</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">CZECHIA</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?#code/MYewdgzgLgBA4gUQEoFkCCA5AmjAvDAcgCYB2ANgIChRJYBlAdQQBEEM9CSBWIqm6GAFU6aDgQAcAFgAMfcAIDCALQQKAEgElR+YtIDMVSlACeABwCmMBSACuYKACdjY0hRgAfTjwIfCU2ZQwQcEhwdTysBDmUGjAUACWAG7m1naOzvgAFKBpTgBcVrb2TgCUeAB8MADegTAA9HUwACYgMBAgALbRABbxYADmlAC+lJRRMXFJKUXpmYwsbCWjDTAAAlAQALTmAB4WcdsODiAOY9GxCcmpxcaZyqqaaCVAA">Playground Link</a></p>

<p>Now, that sure is better. The constant’s name tells the developer what they work with.</p>

<p>This is, in fact, a way that is popular in the Redux community for Redux actions (Or, should I say <a href="https://phryneas.de/redux-typescript-no-discriminating-union">was popular</a>?).</p>

<p>Still, we can identify problems. First, nothing forces you to use these constants. So if it slips the usually meticulous reviewer’s eye, you can end up with a mixed approach: constants and magic strings. Second, the code is not very elegant, we either have to repeat the value in the type definition or use a strange-looking <code class="language-plaintext highlighter-rouge">typeof</code> operators. In either way, adding or removing means a change in two places.</p>

<h3 id="constant-dictionary">Constant dictionary</h3>

<p>Hmm, maybe there is a way to combine them all in one. When we look at the code generated for an Enum, we might think: can we just use that dictionary in the first place?</p>

<p>This works. And it is really close to Enum:</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">Country</span> <span class="o">=</span> <span class="p">{</span>
  <span class="na">Germany</span><span class="p">:</span> <span class="dl">'</span><span class="s1">DE</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">Sweden</span><span class="p">:</span> <span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">USA</span><span class="p">:</span> <span class="dl">'</span><span class="s1">US</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span> <span class="kd">as const</span>

<span class="kd">type</span> <span class="nx">Country</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">Country</span><span class="p">[</span><span class="kr">keyof</span> <span class="k">typeof</span> <span class="nx">Country</span><span class="p">];</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">Country</span><span class="p">.</span><span class="nx">Sweden</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">CZ</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?ssl=16&amp;ssc=23&amp;pln=1&amp;pc=1#code/MYewdgzgLgBAwiArmKAnAnjAvDA3gKBhgHEBTVAWwEMx0AuGAcgBEBRRgGkJgGUB3UgBNSYBox7suRAKo8AgmNmd8AXxhUIMUJCj58UdAAdS8JCgzYYB4yABmp5GnQBtANal0dq0dJeEjjABdAG5uInCIonxtaBgIUig5YCgASwA3Un9zTBwAClAA+gdsgEpsAD48bgB6aphBEDiQCgSACxSwAHNVPXjE5PTMsydcrKcAOn4hERK9WpgAASgIAFpSAA9jZLXUVBBUfD6k1IyxjFzGOAAtRhKgA">Playground Link</a></p>

<p>Weel, it’s not terrible. But it’s not great either.</p>

<p>Let me go through some points to keep in mind.</p>

<ol>
  <li>The dictionary has to be declared <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions"><code class="language-plaintext highlighter-rouge">as const</code></a>. This prevents the type engine to infer the type as general dictionary <code class="language-plaintext highlighter-rouge">Record&lt;string, string&gt;</code>. This is OK.</li>
  <li>The <code class="language-plaintext highlighter-rouge">Country</code> dictionary is a value and not a type. We need to define the type separately. It’s a cryptic command, one I always have to google – not so OK. Fortunately, the type can be named the same as the dictionary, so from now on it’s the same as Enum, right? Well, no.</li>
  <li>As in the previous case, nothing truly ties the dictionary to the function arguments. Calling <code class="language-plaintext highlighter-rouge">setActiveCountry('SE')</code> raises no error. The <code class="language-plaintext highlighter-rouge">Country</code> type is, in the end, just another disjoint union of iteral types again. The benefit is that changes are made only in one place. This is Boo (or at least Meh).</li>
</ol>

<h2 id="enums-the-right-way-my-way">Enums <del>the right way</del> my way</h2>

<p>For years, I’d been using the previous techniques to avoid Enums.</p>

<p>And then one day on one PR someone asked: ‘Why?’.</p>

<p>I was in the middle of my reply when I decided to fact-check some points and, …, and I discovered how wrong I’d been. There were two important properties of Enums that made them <em>superior</em> to anything else. Even for people that worry about moving back to vanilla JavaScript one day.</p>

<h3 id="string-enums">String Enums</h3>

<p>Instead of depending on the source code order to define the value of an option in an Enum, you can define it yourself.</p>

<p>The following code is so close to the dictionary example above, just much cleaner.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">enum</span> <span class="nx">Country</span> <span class="p">{</span>
  <span class="nx">Germany</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">DE</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">Sweden</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">USA</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">US</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">Country</span><span class="p">.</span><span class="nx">Sweden</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">CZ</span><span class="dl">'</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?ssl=1&amp;ssc=1&amp;pln=18&amp;pc=1#code/KYOwrgtgBAwg9mEAXATgTygbwFBSgcWBQgEMQMBeKAcgBEBRagGlygGUB3YAE1CiuptGLPAFU2AQX41xzbAF9WeZSrzYAxnBABnJFG3AkE9UgCWAN2DxEqSlAAUmm+gBcsBMnQBKfgD4srAD0gVDccPpwEIYAFqYgAOYK2NgGRiYWVh629taeaAB0nDygXsnBUAACSNoAtMAAHgAOwCZ1KChwKCmGxmaWudnUMABa1KXY5VW1Dc2tRB1dqb0ZA+j2goylQA">Playground Link</a></p>

<p>Again, let’s discuss some more or less obvious observations:</p>

<ol>
  <li>It uses equal signs, not colons. Do not ask me why. Still, it’s very close to object literal.</li>
  <li>The values must be all strings. Other values are not supported. (Technically, numbers can be used, but they bring no advantage. Stick to strings.)</li>
  <li>You have to use the Enum values everywhere (for example <code class="language-plaintext highlighter-rouge">Country.Sweden</code>) where an Enum value is expected. Passing the same string doesn’t work (for example <code class="language-plaintext highlighter-rouge">'SE'</code>). This makes refactoring a headache-free process. And your codebase stays consistent.</li>
  <li>However, it’s not all unicorns and rainbow. The generated code is a) still there and b) still (kind of) ugly.</li>
</ol>

<p>‘How on earth you want to improve that, Robin?’ you might ask</p>

<p>You’re in for a treat.</p>

<h3 id="constant-string-enums">Constant, string Enums</h3>

<p>The second improvement that helped me cross the Enum Rubicon (‘The type is cast!’, sorry, sorry, I had to) is constant Enum or <a href="https://www.typescriptlang.org/docs/handbook/enums.html#const-enums">const Enum</a> for short.</p>

<p>How does it look like?</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="kr">enum</span> <span class="nx">Country</span> <span class="p">{</span>
  <span class="nx">Germany</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">DE</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">Sweden</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">USA</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">US</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
             
<span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">:</span> <span class="nx">Country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="nx">Country</span><span class="p">.</span><span class="nx">Sweden</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">CZ</span><span class="dl">'</span><span class="p">)</span>

<span class="c1">// @ts-expect-error</span>
<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="https://www.typescriptlang.org/play?#code/MYewdgzgLgBApmArgWxgYRIsUBOBPGAbwCgYYBxOHZAQzAIF4YByAEQFFmAaUmAZQDucACYIYTZn048yAVT4BBcS3ndiAX15ltOssVCRYEOFAXAoASwBucDFlyMYAClD38ALnSZs+AJTiAPiJeAHoQmGEQGAgQZBMACwswAHMNYmJjU3NrW28HJzsfPAA6QREEX3SwmAABKAgAWjgADwAHOHMmnBwQHAyTM0sbQvzmNAAtZkriarrGlvbOqh6+zMGckfwnSU5fIA">Playground Link</a></p>

<p>Wait, wait, I’m not pulling your leg.</p>

<p>It is a letter-to-letter, carbon copy of the previous code, except for the addition of the <code class="language-plaintext highlighter-rouge">const</code> in front of the <code class="language-plaintext highlighter-rouge">enum</code>.</p>

<p>The functionality is exactly the same, too. Looking at the list items above: 1. is the same, 2. is the same, 3. is the same, 4. is… NOT the same!</p>

<p>There is no code generated for the const Enum. This is what the output of the previous code look like:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">setActiveCountry</span> <span class="o">=</span> <span class="p">(</span><span class="nx">country</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="c1">// do something</span>
<span class="p">}</span>

<span class="nf">setActiveCountry</span><span class="p">(</span><span class="dl">'</span><span class="s1">SE</span><span class="dl">'</span> <span class="cm">/* Sweden */</span><span class="p">)</span>
</code></pre></div></div>

<p>Yes, all the values are now inlined in the place of use. There is no clue that there ever was an Enum. Except, maybe, for the helpful comment.</p>

<p>In the end, the result is the same as in the very first alternative we talked about: the disjoint union of literal types. Yet, it is so much easier to use and safer in all regards.</p>

<p>To summarize, with constant, string Enums you get all the benefits of string Enums (type checking, debuggable, not replaceable by string) and of writing it directly (no extra code).</p>

<h2 id="constant-enums-are-a-one-way-street">Constant Enums are a one-way street</h2>

<p>Before we go next, I need to warn you about const Enums. They are not a drop-in replacement every time.</p>

<p>What’s the issue? There is no way to get a label for a value. You see, there is no dictionary, there is no code generated at all. So if you have value, say <code class="language-plaintext highlighter-rouge">'SE'</code>, and you want its label for logging, <code class="language-plaintext highlighter-rouge">Sweden</code> in this case, you will not be able to.</p>

<p>That is a small inconvenience, you should keep in mind.</p>

<p>Also, if you need to access the labels for something else than logging, it might mean that Enum is not for you. Enum labels should have a meaning only for the developer.</p>

<h2 id="constant-enums-can-be-huge">Constant Enums can be huge</h2>

<p>One great use case I found of constant Enums, is that you do not care about the number of items in an Enum. There could be a const string Enum of all the countries in the world and if you only use three, just these three will make it to the production code. The rest would just disappear. And code autocomplete still works with no issue.</p>

<p>In our service code, we now have a share const string Enum with all existing HTTP response codes (excerpt):</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="kd">const</span> <span class="kr">enum</span> <span class="nx">Success</span> <span class="p">{</span>
  <span class="nx">OK</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">200</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">Created</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">201</span><span class="dl">'</span><span class="p">,</span>
  <span class="c1">// …</span>
<span class="p">}</span>

<span class="k">export</span> <span class="kd">const</span> <span class="kr">enum</span> <span class="nx">ClientError</span> <span class="p">{</span>
  <span class="nx">BadRequest</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">400</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">Unauthorized</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">401</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">PaymentRequired</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">402</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">Forbidden</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">403</span><span class="dl">'</span><span class="p">,</span>
  <span class="nx">NotFound</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">404</span><span class="dl">'</span><span class="p">,</span>
  <span class="c1">// …</span>
<span class="p">}</span>

<span class="c1">// …</span>

<span class="k">export</span> <span class="kd">type</span> <span class="nx">HttpStatusCode</span> <span class="o">=</span>
  <span class="o">|</span> <span class="nx">InformationalResponse</span>
  <span class="o">|</span> <span class="nx">Success</span>
  <span class="o">|</span> <span class="nx">Redirection</span>
  <span class="o">|</span> <span class="nx">ClientError</span>
  <span class="o">|</span> <span class="nx">ServerError</span>
</code></pre></div></div>

<h2 id="what-makes-a-great-enum">What makes a great Enum</h2>

<p>Const string Enums.</p>

<p>That’s it.</p>

<p>That is what I now use everywhere.</p>

<p>Before commit, I make sure each Enum fulfills the following two conditions:</p>

<ol>
  <li>All Enum options have a defined custom string value.</li>
  <li>The Enum is declared as <code class="language-plaintext highlighter-rouge">const</code>.</li>
</ol>

<p>I think this combines the benefits of TypeScript with the eloquence of pure JavaScript. A superb developer experience with close to zero impact on the result.</p>

<blockquote>
  <p>Do you use Enums in your code? Do you avoid language features that are not considered for ECMAScript? Tweet a reply</p>
</blockquote>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[Since the very first moment I learned about TypeScript, I knew there's always goona be this one thing I'll hate on: Enums. So un-elegant, so old-school, and so why-do-you-polute-my-runtime. Well, I was wrong. I use Enums now. At least some of them. Let me show you.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/f_auto/v1618775493/yan-ots-FF14FKgecyM-unsplash_z8i48p.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/f_auto/v1618775493/yan-ots-FF14FKgecyM-unsplash_z8i48p.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Engineering Managers Should Not Have the Best Tech Skills in Team</title><link href="https://robinpokorny.com/blog/engineering-managers-should-not-have-the-best-tech-skills-in-team/" rel="alternate" type="text/html" title="Engineering Managers Should Not Have the Best Tech Skills in Team" /><published>2021-03-19T21:35:45+00:00</published><updated>2021-03-19T21:35:45+00:00</updated><id>https://robinpokorny.com/blog/engineering-managers-should-not-have-the-best-tech-skills-in-team</id><content type="html" xml:base="https://robinpokorny.com/blog/engineering-managers-should-not-have-the-best-tech-skills-in-team/"><![CDATA[<p>Recently I was re-reading one of my favorite engineering articles <a href="https://www.thekua.com/atwork/2019/02/the-trident-model-of-career-development/">The Trident Model of Career Development</a> by Patrick Kua. The sentence that caught my eye this time was a note about the role of a Tech Lead:</p>

<blockquote>
  <p>They should have good but not necessarily the best [tech] skills in the team they are leading.</p>
</blockquote>

<p><em>‘How does this apply to an Engineering Manager?’</em> came to my mind instantly. And my initial response was that it’s the same. Yet, after some more thought and thinking about the Engineering Managers I’ve met, I was not sure. Then I made my mind: no, it’s not the same. Now, I think that <strong>it is actually dangerous when an Engineering Manager has the best tech skills in the team</strong>.</p>

<p>Let me show you why.</p>

<h2 id="1-they-cannot-utilize-it">1. They cannot utilize it</h2>

<p>Becoming a manager is a big lateral step for an engineer. While they can draw from their tech experience, being a manager requires a very different set of skills, and–what makes it even more challenging–many of these will be completely new for them. There are so many activities that are not coding, reviewing, or architecting. The new manager simply doesn’t have the time to use their tech skills as they did before. That means that the team and the company now lost a significant portion of tech contributions.</p>

<p>The team is not the only one who is unhappy about it; in fact, and I’ll bet on this, the manager is even more unhappy about it themself. In my previous experience, I saw many brilliant senior engineers who wanted to grow and become an Engineering Manager seemed so natural. Often they were told that the new responsibility will only mandate 10 or 20 % of their time. What a lie that was, as they soon found out.</p>

<p>There were three outcomes I’ve witnessed: not many of the managers accommodated and let the tech go (at least partially); some felt guilty and coded in overtime; and quite a few decided that management was not for them and went back to senior engineers. (A side note for the last case: since becoming an Engineering Manager is often seen as a promotion, most of them rather left the company and applied to a senior engineering position elsewhere.)</p>

<h2 id="2-they-will-be-a-bottleneck">2. They will be a bottleneck</h2>

<p>Connected closely to the previous point, the team might be waiting for code contributions, PR reviews, or comments on RFCs longer.</p>

<p>The number one comment I hear from new managers is about the number of meetings they are expected to attend. This not only deducts from their hours in a day directly but because of the workday fragmentation and constant context switching it is more difficult to find a longer time for uninterrupted work in between the meetings.</p>

<p>This will become a big issue when the task is extremely time-sensitive, like when there is an incident and the best person available should lead the detailed debugging. While avoiding huge losses for the company, the manager will build up a personal debt of materials they need to read, meeting recordings they need to watch, and postponed decisions they need to make.</p>

<h2 id="3-they-will-cause-sub-optimal-decisions">3. They will cause sub-optimal decisions</h2>

<p>Speaking of decisions, there is a significant risk that the team will make some bad tech decisions. Or at least not as good decisions.</p>

<p>Why? In simple words, it’s difficult to disagree with the person who evaluates your performance and decides on your salary, bonuses, and promotions. This whole desire to please one’s superior might very well be subconscious. Yet, it creates a disbalance that might result in worse tech decisions made.</p>

<p><em>There are some great stories about preconceptions the managers had to fight in Kim Scott’s <a href="https://www.radicalcandor.com/the-book/">Radical Candor</a>.</em></p>

<p>I’m not saying that it is not possible to avoid it, but it requires that the manager is aware and puts some compensation processes in place. They also have to work on increasing the level of psychological safety among the team members.</p>

<h2 id="what-should-i-do-when-this-is-my-case">What should I do when this is my case?</h2>

<p>Are you a manager that has the best tech skills in the team? Do you wonder what to do next?</p>

<p>First, this is a fairly common scenario and I know many teams like that that work just fine. The key is to acknowledge that there are some potential risks and be vigilant about their signs.</p>

<p>The best, however, is to stop being the tech go-to expert in the team. Of course, that doesn’t mean you should become worse or leave your manager post. It means actively working on growing your report’s skills. It means extensive knowledge sharing. It means grooming your successor (or successors).</p>

<p>Lastly, you should become comfortable in your position. Accepting and embracing that there will be people better than you in technology, in skills you’ve been so proud to possess. Knowing that the value you bring has shifted from individual strengths to multiplying strengths of others.</p>

<blockquote>
  <p><em>Are you an engineering manager that balances tech and people skills? Who do you think should be best at tech in a team? Tweet a reply</em></p>
</blockquote>

<hr />

<h3 id="related-articles">Related articles</h3>

<ul>
  <li><a href="https://www.toptal.com/engineering-team-manager/engineering-manager-role-explained">People, Product, and Technology: A Beginner’s Guide to Engineering Management</a> at Toptal blog</li>
  <li><a href="https://www.thekua.com/atwork/2019/02/the-trident-model-of-career-development/">The Trident Model of Career Development</a> by Patrick Kua</li>
  <li><a href="https://www.patkua.com/blog/5-engineering-manager-archetypes/">5 Engineering Manager Archetypes</a> by Patrick Kua</li>
</ul>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[Recently I was re-reading one of my favorite engineering articles The Trident Model of Career Development. The sentence that caught my eye this time was a note about the role of a Tech Lead: ‘They should have good but not necessarily the best tech skills in the team they are leading.’ How does this apply to an Engineering Manager?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_crop,f_auto,g_center,h_1080,w_1920/v1616191174/marvin-meyer-SYTO3xs06fU-unsplash_a6c8oa.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_crop,f_auto,g_center,h_1080,w_1920/v1616191174/marvin-meyer-SYTO3xs06fU-unsplash_a6c8oa.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Are open-source databases dead? [Quora answer]</title><link href="https://robinpokorny.com/blog/are-open-source-databases-dead-quora-answer/" rel="alternate" type="text/html" title="Are open-source databases dead? [Quora answer]" /><published>2021-03-05T16:08:51+00:00</published><updated>2021-03-05T16:08:51+00:00</updated><id>https://robinpokorny.com/blog/are-open-source-databases-dead-quora-answer</id><content type="html" xml:base="https://robinpokorny.com/blog/are-open-source-databases-dead-quora-answer/"><![CDATA[<blockquote>
  <p>This is an answer to a Quora question: <a href="https://www.quora.com/Are-open-source-databases-dead/answer/Robin-Pokorn%C3%BD">Are open-source databases dead?</a>.</p>
</blockquote>

<p>Yes, they are dying (this is no joke answer).</p>

<p>Sure, many open-source databases are being used and maintained every day. And, of course, any open-source software will exist and can be forked by anybody. So on the technical level, they cannot die.</p>

<p>However, we have seen several big open-source databases die in the past years. MongoDB, Redis, CockroachDB, TimescaleDB, and–most recently–Elasticsearch. All of those databases ceased to be open-source.</p>

<p>Let me show it on the example of MongoDB and Elasticsearch. Both of the companies behind the databases decided to switch to Server Side Public License (SSPL) which is not considered to be an open-source license. Since this license allows free (as in beer) use for <em>some</em> use cases we will likely be seeing them for quite some time. It’s nevertheless a death of an open-source project.</p>

<p>The reason cited by both projects is… Amazon. More specifically AWS. You see, Mongo and ES were developed by companies and these companies not only lead the project development, but they also hold the trademarks etc. They both also make money on providing some services for their DB, be it consulting, paid extensions, or DBaaS (database-as-a-service) hosting. Historically, publishing open-source software and making money on the services worked great and for many companies, it was a viable business strategy (yes, open source is a business strategy).</p>

<p>In the world of AWS (and other cloud providers) it creates an asymmetrical relationship: AWS can provide and charge for their DBaaS based on an open-source database while paying nothing back to Mongo or Elastic (Amazon has the manpower to support it themselves even on large scale). Which is completely OK under the open-source licenses.</p>

<p>Both of those companies realised that their business strategy was wrong and open-sourcing their DB was a mistake (from the business point of view). So they changed the license to a non-free (as in speech) and non-open one. This created some controversy as relicensing open-source is generally not possible, they took advantage of a clause in CLA that every contributor had to sign.</p>

<p>(Side note, this lowered already low trust in CLAs. A problem for some mostly big companies, that feel they need some extra intellectual property protection and still want to have an open-source program.)</p>

<p>If I were starting a business in providing a database engine now, I’d really think about open-sourcing it based on the experience of Mongo and Elastic. And we see exactly that already, with DBs like Fauna or Firebase not being open-sourced at all.</p>

<p>So <strong>I think that open-source databases are dying</strong> because we might see less and less of them published in the future.</p>

<hr />

<h3 id="related-articles">Related articles</h3>

<ul>
  <li><a href="https://www.theregister.com/AMP/2021/01/22/aws_elastic_fork/">And just like that, Amazon Web Services forked Elasticsearch, Kibana. Was that part of the plan, Elastic?</a> on The Register</li>
  <li><a href="https://drewdevault.com/2021/01/19/Elasticsearch-does-not-belong-to-Elastic.html">Elasticsearch does not belong to Elastic </a>on Drew DeVault’s blog</li>
  <li><a href="https://www.elastic.co/blog/licensing-change">Doubling down on open, Part II</a> on Elastic blog</li>
  <li><a href="https://www.cockroachlabs.com/blog/oss-relicensing-cockroachdb/">Why We’re Relicensing CockroachDB</a> on Cockroachlabs blog</li>
  <li><a href="https://blog.timescale.com/blog/building-open-source-business-in-cloud-era-v2/">How we are building a self-sustaining open-source business in the cloud era (version 2)</a> on Timescale blog</li>
</ul>]]></content><author><name>Robin Pokorny</name></author><summary type="html"><![CDATA[Yes, they are dying (this is no joke answer). Sure, many open-source databases are being used and maintained every day. And, of course, any open-source software will exist and can be forked by anybody. So on the technical level, they cannot die.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_north,h_1080,w_1920/v1617482051/qinghill-GMU6ldtMxGQ-unsplash_sf7dbu.jpg" /><media:content medium="image" url="https://res.cloudinary.com/dljslvfla/image/upload/c_fill,f_auto,g_north,h_1080,w_1920/v1617482051/qinghill-GMU6ldtMxGQ-unsplash_sf7dbu.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>