Multigres: Bringing Horizontal Scaling and Enterprise Operations to PostgreSQL (Sugu Sougoumarane)
Watch on YouTubeVideo summary
Sugu Sougoumarane introduces MultiGrids as a comprehensive solution that redefines the approach to PostgreSQL databases by extending beyond simple sharding to solve holistic operational problems through three core pillars: cluster management, sharding, and materialization. The system addresses the reality that "Postgres doesn't run itself" by automating critical tasks such as backups, restores, connection pooling, and failovers via a pluggable provisioner architecture. This architecture deploys components like the multi-pooler, Postgres instances, storage, and a specialized multi-gateway that utilizes modeless, multi-threaded connection pooling to track statement metadata safely without requiring special client configurations. Furthermore, MultiGrids redefines consensus not merely as node agreement but as a mechanism for durability, implementing explicit rules derived from Flex Paxos that guarantee data integrity regardless of topology or quorum size, while coordination is handled by separate orchestrators to allow dynamic scaling without breaking protocol guarantees.
In the realm of sharding, the system challenges the limitations imposed by the CAP theorem by adopting a philosophy that keeps related data together to maintain ACID properties and availability even at petabyte scales. This is achieved through a pluggable sharding scheme that allows users to define distribution strategies via JSON files, ensuring that related rows are collocated on the same shard to enable single-shard transactions and efficient join operations pushed down by the multi-gateway. The speaker highlights that while MultiGrids is optimized for high-scale OLTP systems and multi-tenant environments where scalability can be achieved through tenant-based or user-based sharding, certain workloads like peer-to-peer payment platforms remain challenging due to their reliance on two-phase commits and single-shard operations. Additionally, the system strongly advocates for local storage over mounted object stores to meet high IOPS demands, though it acknowledges tiered storage as a viable option for archiving infrequently accessed data.
The third pillar, materialization, serves as a powerful tool for enabling zero-downtime operations in sharded systems by reversing replication streams, which allows administrators to stop writes to a source table and redirect them to a materialized copy for seamless migration or maintenance. This versatility facilitates safe PostgreSQL version upgrades with instant failback capabilities, re-sharding via filtered materialization, and the optimization of cross-shard joins by spraying small reference tables across all shards. Schema deployments can also be executed without downtime by creating new tables with added columns before failing over, with all these operations designed to be reversible and safe with a simple command. However, a primary architectural headache identified is PostgreSQL's reliance on physical replication via Write-Ahead Logs (WAL), which limits control over replicas and prevents advanced maintenance tasks like running VACUUM on a replica before failover, thereby potentially causing disruption during critical maintenance windows.
Ultimately, MultiGrids aims to solve these persistent headaches by providing a flexible framework where users can define custom durability policies, such as cross-zone or cross-region requirements, while maintaining consensus invariants through dedicated coordination layers. The system ensures zero errors during planned failovers by holding traffic until the new leader is ready and supports cell-aware routing to keep reads local within zones or regions, having demonstrated the ability to tolerate network partitions for extended periods. By combining these innovative approaches to cluster management, sharding, and materialization, MultiGrids offers a robust platform that not only enhances scalability but also provides the operational flexibility needed for modern enterprise environments, proving that scalable distributed databases are achievable when designed with novel solutions to traditional constraints.
Read the full video transcript
[music]
>> I don't give a [ __ ] about my sequel.
I don't give a [ __ ] about auto go.
>> [music]
>> I don't give a [ __ ] about CLICK HOUSE.
I POST DRESS.
>> [screaming]
>> I DON'T GIVE A [ __ ] ABOUT ANYBODY BUT
ME.
This is it. We're super excited. We're
having the great Sugo here with us. Uh I
he doesn't need introduction, but like
he's like the distributed database guy
for years. Uh he built the test at
YouTube, but one of the world's largest
uh MySQL clusters at YouTube. Then he
was a co-founder of uh PlanetScale. And
in the last year or so, he's been now
Supabase building out a sharded version
of Postgres called MultiGrids. So, as
always as while Sugo is giving his talk,
if if you have any questions, feel free
to unmute yourself and fire away anytime
and that way he's not talking to himself
for an hour on Zoom. And then and of
course, Sugo, thank you coming back a
second time. The last time you gave a
talk with us is during the pandemic.
It's now 5 years later to talk about
MultiGrids.
The floor is yours. Go for it.
Cool. All right. Actually, as uh I
forgot that uh I had to introduce
myself.
Uh so, I guess I'll I'll start with a
story
um
about my oldest interaction with
Postgres. My oldest interaction with
Postgres was in 1996.
Or 90 uh
somewhere around that time, 96 or 97.
This was when uh
uh Stonebraker had built this company
called Illustra.
And I was at Informix at that time and
Informix acquired Illustra.
And I was so fascinated by uh his work
that I actually transferred myself into
the Illustra team and uh worked on
building uh
DataBlades, which is actually Illustra's
uh invention.
And believe it or not, that uh that
experience actually inspired many of
Vitess's designs and many of uh
MultiGrids's designs even to the day. Uh
it was such an awesome experience.
Anyhow, and uh the the other part is the
last time I gave a talk uh for Andy was
about uh Vitess.
And uh I ran out of time.
So, I my hope is to uh not have that
happen again. So, let's see if that
happens.
Uh okay.
So, about uh MultiGrids. Um
most of you think that MultiGrids is a
sharding solution for Postgres and that
is what it intends to be.
But uh I'd like to see MultiGrids as
much more than uh just that, uh which is
um
MultiGrids actually the goal is to
redefine how we approach databases. So,
when we started this project, we kind of
took a look at, you know, where the
Postgres ecosystem is, what is the
tooling, what are the problems people
face. And then we found quite a few
issues with how things are in the state
of the art with Postgres and we thought,
you know, we should take a fresh look at
things and these are the kind of some of
the things that our thoughts, you know.
One thing we realized is Postgres just
doesn't run itself. If you start running
Postgres, soon you realize that you need
to do backups and restores, you need to
worry about connection pooling, you need
to worry about failovers. So, all these
things come into play and there's a lot
of tooling that is required for Postgres
to run well.
Uh the other thing is we have noticed is
that people kind of, you know, have
learned to accept some of the problems
that exist in Postgres.
And we said, let us see what what can we
do to, you know, why should we have to
accept these problems, you know? Can we
really solve these problems and solve
them better and rethink about how people
why people have accepted. So, I'll I'll
as I go into the talk, I'll talk I'll
you'll see how we approach some of the
problems that Postgres has in this area.
And the other one is
um
uh the tooling uh ecosystem is kind of
fragmented. Um
There is like each tool solves a
specific problem within Postgres. But a
problem has a blast radius, right? And
uh and then when two tools come into
play, they need to cooperate and we
didn't see much of that happening. And
that is another problem that uh
MultiGrids solves.
So, essentially what our goal is is to
be to have MultiGrids solve all your
problems uh holistically. And the goal
is that once you are
uh once you use MultiGrids, you
shouldn't want to go back and use
anything else. That's kind of our goal.
Whether we'll succeed or not, we don't
know, but that's kind of what our
objective is.
So, if you look at MultiGrids, there are
I think of it as three pillars. These
are the three main areas of MultiGrids.
So, the first area that MultiGrids
solves is everything about cluster
management.
The second area is uh
uh how to do sharding.
And the third area is called
materialization.
So, these three features work together
to actually um
the these three these three put together
is actually what MultiGrids is. And
these three concepts actually come from
Vitess. Vitess has all these three
concepts also.
So, what about cluster management? So,
cluster management essentially goes back
to
uh the first statement I made, which is
Postgres doesn't run itself.
Everything that we do to make sure that
Postgres runs itself comes under cluster
management.
Okay. Uh the first part of uh there are
a few sub parts within the cluster
management. The first one is the
provisioner.
What the provisioner does is make sure
that um
it uh it does resourcing and component
starts. So,
uh in MultiGrids, this is actually a
Kubernetes operator.
But the by design, the provisioner is
pluggable. So, today, let's say you
don't want to run MultiGrids in
Kubernetes,
you can, for example, provide a um you
know, Teradata um the Terraform, sorry.
Uh Terraform operator and uh that can
then deploy MultiGrids on your own
cluster without the need to run under
Kubernetes.
And uh what the provisioner does is make
sure it gets all the resources, starts
all the MultiGrids components, and then
that's its job is done. After that,
MultiGrids takes care of itself. The
components know how to discover
themselves and wire themselves up
against each other.
Okay. So, the next part is uh connection
pooling.
So, connection pooling is kind of a mess
today in uh Postgres. You know, there
are a lot of limitations and because
there is nothing better, people have
learned to live with it. So, what we
have done is we have solved connection
pooling the right way.
First of all, in MultiGrids, connection
pooling has no special modes.
Uh if you like if you use PG Bouncer,
for example, you have to connect and be
in transaction mode. If you're in
transaction mode, there are some things
you can't you can't do. And if you're in
the other there is the other one called
session mode, I think. And in that,
things you cannot do transactions.
In MultiGrids, uh there is no need for
you to worry about it. You connect to
MultiGrids as if it's a Postgres server.
You don't have to worry about
transaction mode or session mode and
just do what you like. But under the
covers, MultiGrids will uh smartly still
have a connection pool and keep it
within the limit of the number of
connections that Postgres can handle.
And the other part is obviously multi
uh it is multi-threaded, which means
that you are not limited to one CPU. You
can
you can run a large connection pool
server.
Uh so, to explain, you may be wondering,
how can you do
connection pooling
and be fully compatible? What if I go
set a variable,
uh
then that connection gets tainted,
uh how do you make sure that, you know,
that tainted connection doesn't get
reused by someone else?
That comes down to how we have
architected uh MultiGrids.
So, uh just to catch up on uh on the
left-hand side, you see this
provisioner. This is basically a
Kubernetes operator. And the way a user
will start MultiGrids by saying that
they'll push a YAML saying create a
cluster for me.
And then what happens is the provisioner
allocates nodes
uh for uh
getting the cluster running. It'll bring
up a few components. It'll bring up this
multi-pooler. It'll bring up Postgres
here and allocate the storage for it.
And on the upper side, it'll bring up
this multi-gateway.
So, you'll wonder like why is this so
complex? Why is this two-layer
architecture? As the system expands, you
will see that all these components are
needed.
Can you maybe share if you're going to
talk about this ahead of time, feel free
to shut me down. Like, can you share
maybe why you picked gRPC over
you know, maybe something that's more
lightweight?
Oh, yeah. I will I was not going to talk
about it. So, let me answer that right
away.
Uh mainly because uh
it is free.
Uh it uh
it has actually a large number of
features that are very very useful,
actually too useful for us.
Uh but there there may come a time where
where we can actually change it to
something better or more efficient. At
this point, it's the best of the worst.
Let's put it that way. Or worst of the
best uh right now. There's a question
from Yeah, Andre, go for it. Unmute
yourself if you can.
Thank you so much. Quick question. Why
not you you you you do my sockets? Why
over the network?
Oh, we do Unix domain sockets wherever
possible. Like, for example, Multipuller
is on the same node as Postgres and we
will use Unix domain sockets there.
So, here actually I can talk a little
bit more about this. Uh the storage,
right, is another one is another
question. Uh should the storage be local
or should the storage be mounted?
And in today's cloud services, most of
the storage is are mounted. The reason
is because uh
durability or HA is not a solved problem
within the Postgres ecosystem. So, the
only safe way to make sure that you
don't lose your data is to rely on a
replicated mounted storage like EBS. Uh
or Google's GCP, I think. Uh yeah. So,
the
uh so, but then, once you have HA, I'll
talk about it. We don't you don't need
the mounted storage.
Uh in a database, I think I'm probably
speaking to the choir. There's a huge
value in having the storage being local
uh because of the complexity of queries.
Uh we'll talk more about that later.
So,
in my logical view, the Multipuller the
Postgres instance and the storage should
ideally be within one node. I see them
as one box.
And uh multi-gateway, uh as a matter of
fact, this is actually an interesting um
uh way to look at things. People talk
about
um separating storage from compute. You
know, you hear this so much that it's it
like if you say that it's taken for
granted. That's actually one of the
worst decisions, in my opinion, for a
database. Uh separating compute from
storage because of the number of IOs
{slash} round trips the database has to
make against storage.
So, the way I uh my retort to that is
yes, uh Multigress also separates
storage from compute, but the storage
API is not a file system. The storage
API is a database API and this is your
storage. The Multipuller, Postgres, and
storage is your storage layer and what
you scale horizontally is the
multi-gateway.
Uh is another way to look at it.
So, the test is the test doesn't have
the Multipuller, right? That that's an
artifact of like
you know, just to be blunt, the crappy
connection handling
of the multi-process architecture of
Postgres. Like, you need the Multipuller
because Postgres
doesn't scale with the number of network
connections. Whereas, like in MySQL,
because it's multi-threaded, it does
scale better.
It scales better, but it's still not as
good. And so, therefore, we do have a
equivalent for that. It's called the VT
tablet. Yeah. So, this is the identical
architecture to Vitess.
Okay.
>> So, like in terms of like
orders of magnitude,
uh a simple like
uh one of our team members
tried to build a demo. On his laptop, he
was able to like make 20,000 connections
to multi-gateway. Hm.
Uh and like with, you know, 100
connections on on Postgres and he was
able to do a demo. So, the the order of
magnitude difference is huge in terms of
what a go process can accept in terms of
as far as connections are concerned. I
mean, would that be because the
multi-gateway is something that you
wrote that Supabase wrote from scratch?
It doesn't inherit any of the C code of
of the existing Postgres infrastructure.
Correct. This is this is uh essentially
copied from Vitess.
Got it. Okay.
So, here
uh you can see that there is a topo
server. That's basically etcd. Uh this
is what Multigress uses as discovery
mechanism for components to find each
other. Like, when a Multipuller comes
up, it publishes itself into the topo.
And the multi-gateways are watching them
and then they discover and connect to
them. So, this is how
uh this mechanism works.
So, in this case,
uh I need to explain uh why
Multigress can handle uh connections
that are stateful. Uh like, you why you
don't need special modes. The reason is
because multi-gateway has a parser.
The multi-gateway parses your statement
and if you set a variable, it knows that
you actually tried to set that variable.
And it connect it transmits that
metadata to Multipuller, at which point
Multipuller actually
tags that connection as having that
taint.
So, if a new connection comes in that
has the same properties, then it will
reuse that connection.
And that is the reason why it is
modeless.
So, you don't have to differentiate
between transaction mode versus session
mode. It is all done for you
transparently.
And
there is still uh some explanation
needed as to why these are two different
layers. They will become obvious as I
move forward with more features.
Because right now, in this architecture,
there's no reason for multi-gateway to
be different from Multipuller. They
could both be the same.
So, the next part is
the consensus protocol.
Uh
So, uh
if you go and look at consensus, um
the problem What What problem does
consensus solve? Right? What is the use
case for consensus? Uh I I talk to a lot
of people, say, "Can you define what
consensus is?" They usually say
something like, "Oh, it's a bunch of
nodes agreeing on it agreeing with each
other, make sure that things don't
diverge."
But the real use case for consensus is
just durability.
When a system accepts your transaction,
it wants to guarantee that it will not
lose that data.
And in today's world,
uh the the definition of durability is
that the data has to be elsewhere.
If it is just within the current node,
then if you lose that node, then you've
lost your data. So, consensus
essentially, what it says is that you
need to be able to make sure that the
data is elsewhere and you can find it.
You know, if this if you
lose the current node, you can find it.
So, so, consensus, in my opinion, like
this from a use case perspective, is not
uh something where uh
bunch of nodes come to an agreement.
Consensus is a way to solve the problem
of durability.
So, this is how essentially uh I
redefined consensus. Uh this is kind of
a very loose uh
loose term, but uh
is it like
What does What is the problem that
consensus solve? Just make sure that I
don't don't lose my data. Make sure that
I can continue, you know, my
transactions if there are failures,
right? So, but then, if you look at
consensus from this perspective,
uh it feels like
uh the consensus protocols uh basically
uh is not an exact match. Uh like uh
here is an example, right? Today, there
are
uh Postgres high availability setups,
two-node high availability setup,
where there's a primary node, there is a
standby, right? If the primary node
fails,
you fail over to the standby
and the standby continues to serve
traffic.
And you rebuild the primary node and
then fail over back to the primary and
continue.
Right? This is a high availability
solution. The solution also solves
durability.
But you cannot make Raft work for this.
You cannot make Paxos work for this.
Right?
But it is a consensus problem.
Uh you all the guarantees of consensus
have to be uh provided by this system
also. There are many other more complex
things that people want. People say, you
know, "I have four zones. I have like I
don't know, I have like
I have two nodes per zone, right? For
me, my durability requirement is that
the data just goes to another zone. You
know, that is enough for me, you know? I
don't care that there are eight nodes.
As long as the data is in a different
zone, it's good enough, right? How do
you express this with the with a
majority quorum, right? So, those are
those are the real industry needs uh
that consensus, as of
uh the state of state of the art today,
doesn't solve, right? So, like the
majority quorum is a major limitation
when it comes to solving real-life
problems. Uh but today, what happens is
people know only that uh
only Raft works and therefore, you know,
they make compromises about saying that,
you know, either you need a three-node
quorum or a five-node quorum. If you
have specific requirements, make sure
you distribute the nodes such way that,
you know, your requirement is met.
And the second problem is actually
deeper, which is
uh these algorithms are all black boxes.
They they don't really uh
you can't really break them up. You
cannot [clears throat] like uh you
cannot make Raft work for Postgres,
right? You use Raft as a black box and
you cannot break it up into smaller
parts.
So, uh what we have done is actually
studied consensus enough.
Uh like the the simple question you ask
yourself is
when Raft does this begin term,
what does it actually achieve, right?
What rules is it trying to follow? Like,
if I changed the begin term to do
something slightly differently, what
would I break, right? Those are
questions that are not answered.
So, what we have done is we have
redefined consensus into a set of rules
saying that if you follow these rules,
uh then your system
will actually satisfy the properties of
a consensus protocol.
And we have also validated that uh
algorithms like multi Paxos, Paxos, and
Raft actually follow these rules.
And these are actually
um very they are all implicitly there
within the algorithms. They're just not
explicit. So, all we did was make them
explicit, and then what we did was we
actually
uh re-implemented consensus within multi
grass
uh on top of Postgres
using those rules. And uh
if you want to know what those rules
are, uh you can go to multi grass.com.
There's a blog series. It's 11-part blog
series. Unfortunately, it's a long read.
But, it actually builds the entire case
for uh not having
uh
to uh where you can actually
re-implement consensus using uh any way
you like.
Uh so, the beauty of this algorithm that
we have implemented is your durability
policy
is actually not part of the core
algorithm.
You actually provide that as a plugin.
You say, "This is my durability policy."
It can be any arbitrarily complex rule.
You can say cross zone, cross zone at
least two zones, or at least two
regions. Whatever you like, right? You
specify that the algorithm is agnostic
of the policy. But, it will make your
policy work for you.
Uh so, that's the property number one.
The property number two is it works on
top of Postgres' synchronous replication
today.
It is not perfect. Uh but, later we plan
to uh
uh prob- uh probably try an extension,
but if not an extension, minor
modifications to Postgres uh so, that
there is a two-phase synced replication,
which will make actually the perfect
consensus implementation.
Uh the other big change we made was in
in a system like Raft, the nodes
themselves do the coordination.
Actually, the act of coordination need
not be done by the nodes, especially
when we are going to allow like 5, 10,
15 nodes in a cohort. It doesn't make
sense for 15 of them to be doing the
coordination. Uh you you'll have fewer
coordinators. So, we separated that as a
separate role. We call them the multi
ox, multi orchestrators. That's what
they stand for.
Uh and the other beauty of this is uh
that uh because of how it is
implemented, you can freely add nodes to
the cohort, remove them. Uh like, oh,
you need more replicas, just add them.
Uh and uh all the invariants of a
consensus protocol are maintained while
these nodes are added and removed. Like,
if you look at Raft, there's a
completely separate section just to add
and remove nodes. In multi grass, it's
actually part of the protocol itself.
So, what does that give us? It gives us
something awesome, which is we now have
theoretical proof to say that we will
never lose your data once it is
committed.
Uh and today there are a lot of systems
that give you high availability, but
they don't give you that guarantee.
But, we can give the guarantee because
of the fact that it is based on a um
based on following the rules of
consensus. And we'll also make sure that
your cluster never diverges.
That's a lot of things I've said. I hope
you have no questions.
Uh but, uh I'll keep going until you
interrupt me.
It's so so
Yeah, go for it, Andy. No, Jim, you let
him rip.
Yeah, I
Uh Sugu, nice to have you here. Hi. I
was wondering if you could go a little
bit deeper into that previous slide
because it sounds very good at the high
level, but you kind of
see that as properties of what you might
get in the consensus protocol. Uh so, I
was wondering if you can maybe bring out
like what specifically
uh uh
is happening over here because, you
know, you could you could look at Raft
and say it has no diversions and data
loss guarantees the
of different flavors. So, maybe just go
click one level deeper into that.
All right. Uh so, let me um
uh this
uh
essentially will explode is likely to
explode into a huge uh So, this is
basically uh in in my blogs Can you see
my screen?
Yep.
Okay. So, this is actually the last the
recap of my blog series. It actually
summarizes
the So, this this basically is the set
of rules that you must follow. If you
follow these rules, these are rules that
I have shown that algorithms like Raft
and Paxos and multi Paxos follow. We
verified them. And also that if you
follow these rules, all the invariants
of a consensus protocol are maintained
is basically what we have concluded.
And these rules uh do not depend on a on
a
majority quorum. They just uh
they can be defined for any arbitrary
set of
uh constraints.
So, that is one.
Uh I know this is this won't be
satisfactory, so let me scroll down
and show you a slightly more practical
Okay.
So, if you
uh when Raft actually performs a leader
change, what does it actually do?
Uh it basically performs the leader
change in two round trips, something
something in that order. But, those two
round trips achieve actually six
different objectives.
And these six uh these objectives are
actually described can be described
functionally,
uh which is one thing is obtain a turn
number. Actually, I call it the obtain a
turn number is essentially it obtains
the exclusive right to perform work,
which means that the one of the rules of
consensus is that
even though there are multiple agents
acting, only one of them can act at any
given point of time. So, that's an
implicit constraint.
Uh it's not explicitly stated in the
protocol, but that's what those
protocols essentially do. And obtaining
turn number allows an agent to
obtain the exclusive rights to perform
its actions. So, in other words, the way
it does it is one, it it revokes the
ability for all previous agents to do
any work.
It also establishes the candidacy, which
is the future leader. The it recruits
the nodes that are needed to
uh get the future leader.
It discovers the most progressed
timeline.
Uh propagates it and establishes the
leadership. So, if you did these five
steps as different things,
you will still maintain all the
properties uh that a consensus system
requires. You don't have to do exactly
what Raft does essentially is
what we have concluded.
I don't know if that makes sense to you.
Got it. Got it. So, I get it that you
have a different uh
interpretation of Raft in terms of
what steps and what are the properties
for it. And so, is the big picture that
you are essentially making this work
with the idiosyncrasies of Postgres and
and uh having that be correct?
Correct. Correct. So, the problem the
thing with Postgres is that Postgres
does its own replication, right? It has
its full sync replication.
Uh but,
um
just that itself is not sufficient for
for us to build a consensus system.
Uh so, that's why we applied
uh these rules. Now, if you if you use
Postgres synchronous replication and
then follow these rules, then this
system
uh becomes compliant and follows uh and
satisfies the properties of a consensus
protocol.
The only additional improvement we've
made is that uh it is not a majority
quorum.
Uh it doesn't have to be. Uh
so, the original
uh paper was by Heidi uh
in 2016.
Yeah, 2016, Heidi Howard published the
Flex Paxos.
This is kind of one level above Flex
Paxos. I think Flex Paxos only talked
about intersecting quorums.
Uh here it is purely durability rules.
Uh
there is no need even need to define
intersecting quorums.
But, your rules are essentially defining
the invariants.
In a high-level property
to your point a higher level than Paxos,
Raft, and using an application, you're
defining
the experience you want to happen,
of which the invariants In order for
those experiences to happen, the
invariants have to be enforced.
Or in other words, what I have done is
uh re-stated the actions performed by
Paxos and Raft as
functional uh
functional achievements and saying that
this is essentially what Paxos and Raft
do under the covers.
Um
And the the operations that they do are
too simple because they only work for
majority quorum is how I would put it.
If it is not a majority quorum, quorum,
then these operations becomes more
complex. How do you break it up into
smaller parts
and more complex operations such that uh
the properties of consensus are
maintained.
But, like like now we're in the weeds
here. Um like
like Paxos has the liveliness property
that you essentially have two-phase
commit. You're not requiring No, sorry.
You're not requiring a majority? Or you
do require
You don't require a majority. You do not
require a majority. But, like you're not
requiring a majority for the you have
like the multi ox, if you go back to
your slides, and then there was like
using like Paxos terminologies, it's
like there's acceptors, followers, or
acceptors, proposers, and then there's
also listeners, who are non-voting
observers
of the system. Yeah, listeners are not
really part of the core algorithm. They
are more of a
uh for people to discover what the
decision is. The core algorithm is only
with acceptors and follow-ups.
Got it. Okay.
Um
Okay, so keep going. This is
fascinating.
But I I think I think what you're you're
sort of relying on
like the
you're sort of the old-school
multi-Paxos where like the you have the
proposer has a lease that's not going to
that just gets renewed. So that way you
don't have conflicting proposals of
updates to the state machine occurring.
You have the one guy that's one or small
number that's just generating these
things. You're relying on that property.
Uh no, not necessarily. The way the way
I would define it is like if you the
simpler way I would put it is if Paxos
uh in Paxos when the when someone ends
up recruiting a majority of the nodes,
what did it achieve, right?
What it has achieved is basically it has
revoked the ability for all previous
nodes from completing any action.
Right? So that's the reason why it can
safely move forward.
And
that uh objective need that
recruiting three nodes is one way to
revoke the previous agent's objective to
make progress.
You could, for example, go to that node
directly and say, "Please stop doing
what you're doing." is also a successful
revocation.
Mhm.
And as long as you revoke the previous
node's property, establish the new one,
and make sure that it resumes from the
last point
uh safely,
uh you have maintained all the
properties that a consensus protocol
requires. And that is essentially all
that Paxos does.
What do you Got it. So the one way to
state this, now I think I'm getting it,
but maybe this is not right. What you're
saying is that in your setup, Paxos is
requiring that everyone eventually
learns about the decision in a passive
fashion at some later point in time, but
you're saying in the specific ecosystem
that you have with the Postgres
replication, you know
who all the actors that are involved,
and you can specifically go and ask them
to do something as opposed to wait for
it to be discovered later. So you're
going to basically get people on the
same consensus sooner because of that.
Is that an accurate way of thinking
about it, or is it something else?
Um
It is more It is more in terms of the
the way I would put it is if you uh a
majority quorum is basically like if you
if you told
multi-Gresil, "Use majority quorum."
that's your durability policy, then it
would be exactly like it its behavior
would be exactly like Raft.
Does that make sense? Yeah.
Uh but if you say, "Oh,
there are eight nodes, I need my data
only for my durability requirement is
only one other node."
uh then it will not look like Raft,
but
when the when a failover happens, the
failover mechanism will actually visit a
lot more nodes, but will make sure that
anything any transaction that was
committed resumes and is not lost. I
don't know if that makes sense.
So the the the the basic idea of Raft is
that it will not lose your data. Right.
So that same property is maintained,
except your tolerance to failure is
different. In Raft, the tolerance to
failure is by majority. In this case,
your tolerance to failure is defined by
the user.
Oh, I see. Okay. That makes sense.
Defined by the user. Okay. Okay.
So, yeah. It's a
I'm trying to you know this this
literally is 10 years of thinking and
trying to compress it all, so it will be
it's hard to explain it in in one go. So
I actually wrote a one-pager, and then
people said I they didn't understand, so
that is what expanded into this 11-part
blog series.
Yeah.
>> All right. So there's a question in the
chat that says, "Can we see it as moving
consensus into another layer? I.e., the
SCD controller that decides which node
is the ultimate leader instead of
internally within the replica group?"
No, this actually that is actually what
we tested. In Vitess, we cheated. We we
leaned on etcd
to
do this consensus. In multi-Gres, it is
pure it is pure
bottom-up consensus protocol.
All right, this is gold. Keep going.
All right, so there you go.
I'm going to run out of time again. Yay.
>> [laughter]
>> But but I'm happy this I'm I'm really
happy that you know this
the the last time I tried to present it,
people
like couldn't understand what I was
talking about, so I'm happy here there
are people
to get this.
All right, so
if you let's go back to the slideshow.
Uh
So we'd already said that connection
pooling has no special modes and is
multi-threaded. So now that you've
brought consensus, connection pooling
acquires two more properties. Uh we give
you automatic replica load balancing,
which means that you connect to the
multi-gateway, and it will and you say I
want to talk to a replica, it'll
distribute your it'll distribute your
reads across multiple replicas.
But the cooler feature is the
follow-the-leader
part, where
multi-gateway always knows who the
leader is and sends the traffic to the
leader.
If there is a failover, it'll follow
that leader. It'll say, "Oh, there's a
new leader now. I'll now send traffic to
the new leader."
And the even cooler feature is if there
is a planned failover,
it'll actually
hold off traffic until the failover
completes, and then sends it to the
leader. So essentially the user will see
So one of our policies in multi-Gres is
no errors served on any planned
operations. So if there's any kind of
planned failover, the user will see no
errors at all.
And uh here is actually a diagram that
shows how
So by the way, our first release
within Superbase at least we are going
to deploy a traditional three-node
system with majority quorum, which means
that one other node should have it from
the primary.
Uh except that we have the mechanism to
come up with more sophisticated
topologies in the future.
Uh there is a question. In the example
you just mentioned, if the durability
requirement is just two nodes, and there
are a lot of nodes to which the changes
are not made durable,
but there are at least two to which it
has been made durable, then how is there
a sense of agreement between all the
nodes that the two nodes we have been
talking about should be considered the
source of truth. This is a fantastic
question.
The answer to this is actually
in the Flex Paxos paper that Heidi
published.
The way you do that is let's say there
are five nodes, right?
And uh
and your requirement is durability is
two nodes,
and you performed a write, that means
that the failover mechanism needs to
recruit at least four nodes.
If the failover mechanism recruits four
nodes, then it is guaranteed to discover
any transaction
that has been made durable. And
therefore uh any transaction that became
durable will not be lost. I don't know
if that answers your question.
The failure case is is more complicated.
And that is actually the wisdom behind
this approach is
uh a consensus protocol does not worry
about performance, but in real life we
do have to worry about performance.
We typically a system does thousands of
transactions per second, but how often
do you do failovers, right? You do
failovers once a day, once a week.
Uh
Once a week, that operation can afford
to be expensive, right?
Uh you want the fast path to be
efficient. So that's the reason you want
fewer nodes, but having a lot of nodes
gives you more latitude.
Cool. Oh, I accidentally
I don't know how to go back, so I have
to go back and click here.
>> [laughter]
>> All right. So here is actually an
zoomed-out diagram.
These smaller boxes are actually the
multi-polar Postgres and storage
together.
So the way it works is
uh these three nodes, for example, are
part of a consensus cohort, and the
multi-arc is an external agent that
watches over them and performs failovers
as needed.
And uh
the way we have designed it is you can
have any number of multi-arcs as you
desire. The multi-arcs do not know about
do not need to know about each other,
and the protocol still works correctly.
No problem at all.
And uh
the arc would connect to a
multi-gateway, and it will say, "I want
to connect to a primary." in which case
the traffic gets sent to a primary.
Uh if it says, "I want to connect to a
replica." then it'll load balance.
And there's actually a special node we
are going to introduce, which is
consistent replica reads, which means
that once you have written to a primary
and you issue a read, it can wait for
the replica to catch up to that point
and then perform the read there for
better distribution.
Cool.
Uh how much time do we have? Okay, I'll
try to wrap everything up within 10
minutes.
You got You got plenty of time. Keep
going.
Okay. Okay.
So, we have integrated backups. I have a
lot of content to cover, by the way.
>> [laughter]
>> We use PG back rest.
So, the consensus protocol actually
works with backups to make sure that you
know, the system like for example, if
you say add a node the node
automatically restored itself from
backup and joins the cohort consensus
system registers it and then it becomes
part of
your
your system.
All right.
And then finally
Multi-Gres allows you to be
has this concept of a cell. I'll
actually it's better shown as in this
diagram.
You can actually define failure zones in
Multi-Gres as cells and then have
traffic routing that are cell aware.
So, the
there are two ideas here. One is
when you have when you are in different
zones in different regions, you don't
want your replica reads to go you know,
across
across zones. You want your reads to be
local. So, that is something Multi-Gres
can do.
The other thing is actually if there is
a
partition network partition, if a cell
gets partitioned, it's designed in such
a way that a single cell can survive by
itself for as long as it can.
And we use this a lot at YouTube because
in YouTube, guess what? People are
mostly watching videos. We could
tolerate like 2 hours of you know,
network partition.
After that, we say okay, no things are
getting stale. We cannot continue to do
this.
This is the olden days. I'm sure the not
tolerances are much lower now. Um
with the current YouTube.
So, I don't I won't go into the details,
but the beauty of all this is the
provisioner now makes sure these things
are up. You don't really need to
maintain this complexity. These these
are components that you know, maintain
by themselves. The one thing you can see
here is that there are six nodes in this
in this cluster. There are team three
multi-arks. The idea is that if there is
a network partition, at least one other
one multi-ark will have enough
connectivity to perform a failover.
So, that's the idea behind this.
All right. Now, switching gears, we are
going into sharding.
Here's a hot take.
I I think I don't have to tell you this.
It is theoretically impossible to build
a scalable
distributed database.
If anybody wants to challenge me
bring me your database and I'll bring it
to its knees.
>> [laughter]
>> What I have to say.
But yes.
Um
Why would a guy who's trying to scale
scalable databases say such a thing?
Well, reality is reality and knowing
these rules, we can make good decisions
is my opinion.
So, here is kind of a quiz of some sort.
We have known the CAP theorem.
We have known that databases required
acid. But these two
No, these two things never met because
CAP was mostly used for key value
replicated stores. But how does CAP come
into play for distributed databases is
the question, right? How does acid
and CAP you know, interact with each
other when it comes to databases?
So, I
I usually explain the difference between
atomic and isolation because that is
something that people get wrong all the
time. I assume you're all educated, so
I'm going to skip that part.
So, and going to go through this
slightly quickly.
So, which part of CAP does atomic
require? Atomicity is a consistency
property.
What about isolation? Isolation is also
a consistency property.
What about durability? Durability was
actually not a CAP property at all
because what is written to disk was
considered durable.
But now with consensus
data becomes durable only when it is
distributed, therefore it starts to
be affected by the CAP theorem. So,
durability is also a consistency
property.
Believe it or not
consistent of acid is the only thing
that has nothing to do with the CAP
theorem because consistent of acid deals
with you know, foreign key integrity and
those kind of things, whereas the CAP
theorem's consistency deals with read
after write consistency.
So, so if you look at this, right?
The simple answer is the database wants
all your data to be together.
If your data is not together, you are
going to lose on availability. That's
essentially what this slide is trying to
tell you.
So
if you're trying to distribute data
you have to know this. You have to know
that you are going to cause availability
issues. Or
if not availability, you're going to
cause things to be slower. You know,
there is not the CAP theorem, there's
the PACELC theorem, right? I don't know
how you spell it, but it's the one that
says if things are distributed, things
are going to be slow.
Which is the Abadi's theorem.
So
how do you
then do
Oh yeah, and the link back.
So, how do you make this work, right?
How do you build a scalable system
where
these properties are maintained and it
is also consistent and it is also
available. The answer is
kind of simple.
Keep the things that have to be together
together. Keep the things that can be
separated separate. So, in reality, if
you're like if you have petabytes of
data in your database
one thing I can tell you for sure
everything is not related to everything
else. You know, there are there will
always be groups of data that are
related there are smaller groups of data
within your large petabytes of system
that are related. If you can bring them
together the correct way
then you mostly get the properties that
you want. You mostly get the best of
both worlds. Basically, in other words,
you get all the acid guarantees that you
want and you get the consistency and
availability part of properties that you
also want.
And that is the philosophy that we use
in Vitess as well as in Multi-Gres.
So
the part One part of sharding is how do
you distribute the data? And this is the
part that most distributed databases
have solved.
And and it's not actually any
hard problem to solve. You know,
distributing the data is
the hard problem to solve in the art of
sharding is how to collocate it, right?
And this is where we believe we've got
the secret formula right. Vitess has a
fantastic
powerful sharding scheme
and
that sharding scheme allows you
to in a formal way
make data that is related to each other
be collocated.
And once you have that
you then have a powerful system that can
scale forever for you.
It won't always work. There is always
there will always be one particular
workload which is not well suited for
this mechanism, in which case you have
to pay the price that you have to pay.
There is no escape from that.
So, the first part of the the first part
of Multi-Gres is the sharding scheme is
also pluggable.
Now, you can see this pluggable thing,
right? This this all comes from my
experience at Illustra, you know.
Make important things pluggable, right?
So,
in Illustra, the index was pluggable, so
so here the sharding scheme can be
pluggable, which means that
if you say I have a JSON file that
decides where the shards live,
Multi-Gres can use that JSON file and
can you know, make it part of our
relational model for sharding.
And you it allows you to collocate
related rows
which allows
multi-gateway to push down joins.
If there are full scans, you can do
scatters and
if you collocate the correct data, most
of your transactions will be single
shard. In other words, your system will
scale to petabytes and will continue to
feel like you know, a small database.
You'll continue to see the performance
of a small database.
Materialization.
What What is materialization, right?
Like what Why is it so important? This
actually is actually the third secret
weapon of
both Vitess and Multi-Gres.
So, what are What is materialization?
Everybody knows materialization, which
is basically
you take a source table and say
materialize this select statement from
that table, right? So, that's a simple
way to
describe materialization.
But you don't realize how powerful it
is.
If you materialize table A into table B
and let's say they are identical.
What you can do is actually if you're
writing to table A
you can you know, at some point of time
say, okay, you know what? Stop writing
to table A, start writing to table B
and reverse the replication from table B
to table A.
Right?
And things continue to work fine and no
one has noticed a difference.
And
if you are in a sharded system
and you do this,
uh
then
uh nothing is disrupted is the last
feature of this materialization.
Why is this so awesome and so powerful?
Why?
Is because of all the things we can do
with this. This is this tooling is so
versatile that we are even calling it
multi-graph. Somebody wanted to call it
multi-graph but because it's as
versatile as graph. So, what can you do
with this feature?
We can migrate all your data from any
anywhere into multi-graph. You can
migrate your data from multi-graph to
anywhere else.
If you're going to upgrade your Postgres
version, we can do it for you, you know.
You're running version 15, you want to
come to version 17,
we'll materialize this table for you in
version 17,
switch over traffic,
everything works fine, continue. Oh,
things are broken, fail back, go back to
the old one, right? Saves uh version
upgrades.
We do re-sharding which is basically a
materialization where we filter by the
sharding key.
Uh
there are use cases where
uh if in a large in a large petabyte
scale database,
you'll have these small tables that are
reference tables, you know, they are
they have only you know handful of rows
or you know tens of thousands of rows,
but those tables have to be joined with
the sharded tables.
In that case, uh these become
cross-shard joins because you know
shards that are there you may have like
500 shards and this is an unsharded
table.
So, what we can do is we can materialize
this reference table, spray it across
all shards,
in which case all your joins become
local joins.
Uh we can do schema deployments, right?
If you say I want to add a column and
that causes Postgres downtime, we can
materialize a
new table with the new column for you
and materialize it and then failover and
then reverse, right? So, the list is
literally endless. You just keep on
adding you have found so many use cases
that um
when materialization becomes a
first-class citizen within multi-graph,
all these things are like click of a
button type of operation and safe
because they all have
uh the ability to undo what you have
done.
And all these put together is uh what
multi-graph is.
So, what is our progress so far?
Uh we have finished cluster management.
We are going to start work on sharding
and materialization. We are behind
uh but the thing that we like is we are
solving problems in ways that people
have not solved before and therefore we
think we we bring awesome value to this
ecosystem and that's why we are super
excited about the future.
And that concludes my talk and I can
answer more questions. If you don't have
more questions, we can go back and nerd
out on more consensus.
>> [laughter]
>> I will applaud on behalf of everyone
else. That was awesome as always.
Again, we have time for questions so
feel free to mute yourself and go for
it. If you want to go first, go for it.
Yeah, I think this is great.
As you I think alluded to a lot of it
depends upon what you're trying to get
out of your database system. So, is
there
class of database workloads that you are
targeting with multi-graph as you build
out this vision?
Maybe
would love to hear your thoughts in
terms of
what is that target? And Yeah, that's a
fantastic question. I actually
>> agents are involved and things like
that, so go for it.
Yeah, I actually I I was meant to I'm
meant to talk about it but I missed it.
Uh so, if you look at uh high-scale OLTP
systems,
uh 90% of them are multi-tenant.
And uh a sharded system is perfect for
multi-tenant workloads.
Uh because
uh you can like you can basically like
you can scale you can go really really
far
uh by sharding by tenant, right? Like um
let's say you have
um
So, like you can go up to the point
where you know a shard contains just one
tenant, right? That's the lowest
uh lowest level of granularity you can
go with multi-tenant sharding.
And
uh so, in that case which means that
typically like um
uh
organizations like Slack are the first
ones where tenant-based sharding did not
scale for them.
And then they actually changed their
sharding key when they used Vitess.
And uh even there
uh
it is actually common sense, right? Like
when a tenant becomes big,
it means that they also have a
sub-sharding key because otherwise
uh if the tenant were themselves, you
know, their own database, how would you
shard the database is the question you
would ask. Most likely those tenants
themselves have sub-tenants.
Which means that they have a second
sharding key and therefore you should be
able to shard by that key. In other
words,
um when a tenant becomes too big, you
will most likely be able to find a way
to break that tenant up into smaller
parts also.
Uh Slack actually went a different route
when they actually
uh sharded by tenant and then they
decided that doesn't scale because some
of their tenants are massive.
They actually switched over to
user-based sharding where
uh each user lives in their own shard
model.
Uh there are some there is one model
which is actually not
uh conducive to sharding which is
uh
the place where
uh P2P things like for example payment
platforms because anybody randomly pays
someone else and that becomes always a
two-phase transaction.
Uh the way Block solved this
uh
previously known as Cash App is uh they
just used a memo system where you'd
subtract money in one shard and write a
journal saying that this money has to go
to the other person and then
uh make the replay that journal in the
other shard and complete it
uh is how they solved it.
Uh but you could also solve it through
2PC.
But what I've noticed is that even in
that case they are
a lot of the operations are single-shard
operations is is what happens.
Uh
But I would say that that that workload
is not easily adaptable to a uh sharded
system.
Uh a local disk can get you so far.
Uh yes.
>> [laughter]
>> The question is uh
is there any The question is are there
any plans to do for utilization of an
object store?
Oh,
uh
I I am I am against even uh using
mounted storage for databases. I I
somehow find find it, you know, like
database is so IOPS-hungry uh that I
want to use uh local storage.
The only time I can think of object
storage is if you have data that is uh
that may be archived on because it's not
uh used as often
is one is when I thought uh when I felt
I I If you ask me, I would go like
people are all go already going the
wrong route by trying to use mounted
storage, you know. We should use uh
we should use local storage um as much
as possible.
Yeah, yeah. I saw great great uh talk
there. Um
Yeah, with a lot of modern systems
nowadays, you see uh utilizations of
object store storage and uh tiering,
right? So, tiering let's say like a
different uh forms of caching, moving
the data
across different tiers, right? Uh
depending on like accessibility
patterns. So, like that's why I brought
that up because local storage are so
constrained local storage, right? And uh
but you see like
>> Yeah, yeah. So, tiering can be yeah.
Uh it can be it can definitely be
uh used. I think Auriol actually has uh
has the ability to do tiered storage. I
don't know how far they are.
Um
Like uh I guess the I come from, you
know, the GitHubs and the Slacks, they
don't care about
tiering. They they want all the data
immediately available
all the time everywhere. They they want
everything everywhere all at once.
That's what That's where I That's kind
of I may be biased by the way. No, no,
no. Yeah.
I like I'm with the with the local
storage and like embedded embedded uh
uh solution. But uh yeah, that's
interesting for sure. Great talk and
yeah, awesome. Thank you for answering
the question.
All right, other questions?
All right, so I'll ask the last
question.
Go for it.
I should say it hi. So, I Yeah, yeah,
sorry.
>> [laughter]
>> Um
So, again, given your experience
uh you know, building out scale version
of of MySQL with Vitess and now scale
version of Postgres with multi-graph,
um
can you share us what are the aspects
that are giving you the most problems in
making this work in Postgres? Like in
terms of like the architecture, you
know, you mentioned the replication
piece.
Um
I see you're a layer above it. You're
not really touching so much the
internals of the system. You're you're
utilizing what already Postgres exposes
to you. But is there any aspect of
Postgres that's caused you the most
headaches in the last year
that you wish Postgres didn't you wish
Postgres didn't do it?
Uh the wall is a big problem for me.
Uh yes, it is uh the reason is because
um the reason is because
you have um
uh
have very little control over the
replicas. There is like the because the
wall is a physical replication method.
It is
You you want to filter what you're
sending when you send the wall or what
do you want to do?
Um
Let me try and see why wall is a
nightmare.
Okay, so it's like
here is what I thought of right? Like uh
I was asking like if
physically replication was little bit
more logical which is actually what
OrientDB does, we can do cool things.
Like for example, one problem I want to
solve is the problem of vacuum, right?
Vacuum runs at an unexpected time of day
and disrupts you, right? If there was
logical replication, what I would do is
I would run vacuum on the replica.
Right? And then fail over to the replica
and then run vacuum on the other replica
for example, right?
With the wall, I just can't do it.
Yeah.
So there are there are
cool things like that with that we
cannot do if we had the wall
replication.
Got it. Okay. Okay. Makes sense.
Okay, awesome. But I miss you girl. You
did it again. Awesome. Thank you so much
for for giving this talk. Great one as
always. I had fun. I had fun. And thanks
for the questions. They are awesome. I
wish I could spend you know more time
talking about consensus. Unfortunately,
it's not enough time. So let's see this.
I mean let's not wait 6 years for you to
give another talk with us, right? Let's
let's you know let's let's do one
sooner, okay? Oh, definitely. Yes, I'll
be I'll be happy to.