<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Vasilios Syrakis - sharding</title>
    <subtitle>A simple blog made with Zola and Duckquill</subtitle>
    <link rel="self" type="application/atom+xml" href="https://cetanu.github.io/tags/sharding/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://cetanu.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-11T00:00:00+00:00</updated>
    <id>https://cetanu.github.io/tags/sharding/atom.xml</id>
    <entry xml:lang="en">
        <title>How to Avoid Sharding Yourself</title>
        <published>2026-07-11T00:00:00+00:00</published>
        <updated>2026-07-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Vasilios Syrakis
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://cetanu.github.io/blog/how-to-avoid-sharding-yourself/"/>
        <id>https://cetanu.github.io/blog/how-to-avoid-sharding-yourself/</id>
        
        <content type="html" xml:base="https://cetanu.github.io/blog/how-to-avoid-sharding-yourself/">&lt;p&gt;I watched a video named &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=rxR4nIQ0hCk&quot;&gt;The Problem Sharding a Database
Solves&lt;&#x2F;a&gt; by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@WebDevCody&quot;&gt;Web Dev
Cody&lt;&#x2F;a&gt;. He has quite a large number of
subscribers, his video popped up on my feed, and I enjoyed the video. Also, the
diagramming tool he’s using is cool and if anyone knows what it is - please
tell me!&lt;&#x2F;p&gt;
&lt;p&gt;However, one thing stuck out to me that I wanted to intercept in order to
provide advice on, based on my own real professional experience.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-part-i-m-focusing-on&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-part-i-m-focusing-on&quot; aria-label=&quot;Anchor link for: the-part-i-m-focusing-on&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
The part I’m focusing on&lt;&#x2F;h1&gt;
&lt;p&gt;It’s not the whole video, it’s just one minor part. Cody delivers on what I
think the point of his video is - to describe how sharding solves a particular
problem - but there is some detail that comes across as a suggestion for how to
implement routing a tenant to the shards and this is what I’ll be discussing.&lt;&#x2F;p&gt;
&lt;p&gt;Cody describes a naive approach where you take some kind of tenant identifier
and hash it, which gives you a deterministic way to determine which shard the
tenant lives on.&lt;&#x2F;p&gt;
&lt;p&gt;He then rightly points out that if you pick this approach, as the number and
size of tenants grows you’ve now made it harder to rebalance your shards, or
migrate tenants, because when you insert new shards, the deterministic hashing
essentially breaks.&lt;&#x2F;p&gt;
&lt;p&gt;This leads Cody to describe a possibly more elegant approach called “virtual
buckets” where instead of a hash being a 1:1 mapping between a tenant and a
shard, you take the modulus of the hash which maps a range of tenants to a
shard instead.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;multi-tenant-routing-with-an-algorithm-is-an-anti-pattern&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-tenant-routing-with-an-algorithm-is-an-anti-pattern&quot; aria-label=&quot;Anchor link for: multi-tenant-routing-with-an-algorithm-is-an-anti-pattern&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Multi-tenant Routing with an Algorithm is an Anti-Pattern&lt;&#x2F;h1&gt;
&lt;p&gt;These methods of routing tenants to shards aren’t broken, but let’s call them anti-patterns.&lt;&#x2F;p&gt;
&lt;p&gt;First, let’s talk about why hashing is an attractive option.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It’s stateless&lt;&#x2F;li&gt;
&lt;li&gt;It’s fast&lt;&#x2F;li&gt;
&lt;li&gt;It doesn’t need a database lookup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But it leaves you open to &lt;strong&gt;operational pain&lt;&#x2F;strong&gt;, even with the use of virtual buckets.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;one-tenant-within-a-bucket-can-dwarf-other-tenants&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-tenant-within-a-bucket-can-dwarf-other-tenants&quot; aria-label=&quot;Anchor link for: one-tenant-within-a-bucket-can-dwarf-other-tenants&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
One tenant within a bucket can dwarf other tenants&lt;&#x2F;h3&gt;
&lt;p&gt;If we just assume that the Pareto principle will play out eventually, you’re
going to have one tenant which consumes 80% of a single shards capacity.&lt;&#x2F;p&gt;
&lt;p&gt;In order to rebalance them, you need to change their identifier. Now you have
to choose between accepting the noisy-neighbour problem where a huge tenant
fights for dominance with the other small tenants on the shard, or you add a
special-case to your hashing algorithm that lives on forever, and most likely
grows, needing to be maintained by operators.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-flexibility-for-isolation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-flexibility-for-isolation&quot; aria-label=&quot;Anchor link for: no-flexibility-for-isolation&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
No flexibility for isolation&lt;&#x2F;h3&gt;
&lt;p&gt;This is semi-related to the above, essentially,  if you wanted to have
different shards, like a “quarantine” shard for misbehaving tenants, or a “free
tier&#x2F;trial” shard, or an “important enterprise customer” shard with only 1
tenant on it, you again have to special-case the algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;These requirements will predictably appear as you grow and get more customers.&lt;br &#x2F;&gt;
Maybe they won’t, but we can take care of this with very little operational
friction as we’ll see later.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rebalancing-friction-doesn-t-go-away&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rebalancing-friction-doesn-t-go-away&quot; aria-label=&quot;Anchor link for: rebalancing-friction-doesn-t-go-away&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Rebalancing friction doesn’t go away&lt;&#x2F;h3&gt;
&lt;p&gt;Cody does point out that even when you add new shards, you still might need to
rebalance tenants, but you can maybe do this with some background process or
lazy migration that writes to both shards at the same time.&lt;&#x2F;p&gt;
&lt;p&gt;For some businesses these might be acceptable operational events that someone
has to take care of, perhaps after-hours or during scheduled downtime.&lt;&#x2F;p&gt;
&lt;p&gt;Note: you &lt;em&gt;can&lt;&#x2F;em&gt; mitigate this particular downside with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Consistent_hashing&quot;&gt;Consistent
Hashing&lt;&#x2F;a&gt; but the others are
still unsolved.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;your-tenants-deserve-their-own-directory&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#your-tenants-deserve-their-own-directory&quot; aria-label=&quot;Anchor link for: your-tenants-deserve-their-own-directory&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Your tenants deserve their own directory&lt;&#x2F;h1&gt;
&lt;p&gt;I know it’s attractive to use clever software to avoid adding infrastructure to
solve a problem, but I think this situation justifies the addition of a
database to act as a lookup table or directory for your tenants.&lt;&#x2F;p&gt;
&lt;p&gt;For the vast majority of businesses, a dedicated Redis or Postgres instance can
serve this purpose and take you very far.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, it is a single point of failure, and if it goes down so does your entire
app probably, but do a little back of the napkin calculation on the probability
of redis (in a cluster, with high-availability), whose only job is to keep key
value pairs, becoming suddenly unavailable for any serious amount of time. It
probably won’t go under 3 nines of availability.&lt;&#x2F;p&gt;
&lt;p&gt;Externalising the tenant routing to a lookup table unlocks advantages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;surgical-rebalancing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#surgical-rebalancing&quot; aria-label=&quot;Anchor link for: surgical-rebalancing&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Surgical Rebalancing&lt;&#x2F;h3&gt;
&lt;p&gt;Your rebalancing goes from a stressful situation of changing the algorithm,
propagating it to your gateways and praying, to a 5 step process that an intern
can execute without bringing the company down.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Identify: you surface a big noisy tenant via monitoring or regular capacity planning&lt;&#x2F;li&gt;
&lt;li&gt;Provision: a new shard is created&lt;&#x2F;li&gt;
&lt;li&gt;Sync: background job to copy data, stream new writes in the meantime&lt;&#x2F;li&gt;
&lt;li&gt;Switch: single atomic database query to point at the new shard&lt;&#x2F;li&gt;
&lt;li&gt;Cleanup: wait a week and delete the old copy&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;better-isolation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#better-isolation&quot; aria-label=&quot;Anchor link for: better-isolation&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Better Isolation&lt;&#x2F;h3&gt;
&lt;p&gt;Before, changing the way hashing works to satisfy the needs of a particular
tenant or tenants meant that you were changing the algorithm for &lt;em&gt;everyone&lt;&#x2F;em&gt;.
This represented a huge blast radius.&lt;&#x2F;p&gt;
&lt;p&gt;With a lookup table, you’re changing one record.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;fives-nines-of-availability-no-i-said-nine-fives&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fives-nines-of-availability-no-i-said-nine-fives&quot; aria-label=&quot;Anchor link for: fives-nines-of-availability-no-i-said-nine-fives&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Fives nines of availability? No, I said nine fives…&lt;&#x2F;h1&gt;
&lt;p&gt;If you’ve somehow reached the point where that lookup table is no longer
sufficient (and you’re still reading this blog? lol), or you just feel
uncomfortable with having to make a lookup on every request to a single point
of failure, there’s a pattern you can employ to scale things further and bring
the probability of an outage to a number approximating zero.&lt;&#x2F;p&gt;
&lt;p&gt;You can actually
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.atlassian.com&#x2F;blog&#x2F;atlassian-engineering&#x2F;aws-scaling-multi-region-low-latency-service&quot;&gt;read&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.atlassian.com&#x2F;blog&#x2F;atlassian-engineering&#x2F;atlassian-critical-services-above-six-nines-of-availability&quot;&gt;about&lt;&#x2F;a&gt;
how Atlassian solved this exact problem using the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Command_Query_Responsibility_Segregation&quot;&gt;CQRS pattern&lt;&#x2F;a&gt;.
However, I’m going to explain it here even more concisely.&lt;&#x2F;p&gt;
&lt;p&gt;CQRS, or “Command Query Responsibility Segregation”, can enable a caching
pattern where distributed nodes are able to keep a local copy of the data that
they can query even while the lookup table is offline.&lt;&#x2F;p&gt;
&lt;p&gt;Distribute caches to each of the gateways that needs the data, and have those caches update  &amp;lt; more detail &amp;gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
