0:23:06 So I'd be curious to learn a little bit
more about the challenges that you were
0:23:10 facing building Replicache and building
Reflect as it relates to the challenges
0:23:16 you've mentioned before in regards to
storage and other challenges we might not
0:23:20 have talked about yet when it comes to
building such a technology for the web.
0:23:24 Yeah.
0:23:26 there's a lot of little things
that you discover when you set
0:23:29 out to do something new like this.
0:23:31 And a lot of times, you know, in
software engineering You know, a lot
0:23:34 of the work comes from like unexpected
places, you know, it's not the
0:23:37 algorithm, it's not the core algorithms
or the data structures or whatever.
0:23:39 It's like dealing with the practicalities.
0:23:42 Like one thing that is really a
quirk of the web that is another one
0:23:45 of the web superpowers, but really
makes this challenging is tabs.
0:23:49 Like, the web has tabs and tabs from
like a platform software developed,
0:23:54 like a software engineering perspective
are weird because they are different
0:23:57 execution environments, right?
0:23:58 It's as if.
0:24:00 You have an application, but it
has like, it has many different,
0:24:03 like, places where code can run.
0:24:05 Many, like, it's as if you had
a bunch of different processes.
0:24:07 They're not, tabs aren't really different
processes, but like, from a software
0:24:10 engineering perspective, they're kind
of like processes because they're
0:24:12 different execution environments that
can have different code in them, right?
0:24:15 Like, you could have different
versions of your app with different
0:24:18 code bases running in each tab.
0:24:19 Like, if the server updated
and and one tab updated, but
0:24:23 the other didn't, you know?
0:24:24 But they share storage.
0:24:26 So that is a weird thing.
0:24:28 Usually when platforms have a situation
like that, where you have processes
0:24:31 or threads, they also have locks
so that you can like protect the
0:24:34 storage and coordinate access to it.
0:24:36 But the web has kind of has like
a fledgling web locks API, but
0:24:40 it is very unused and tested.
0:24:42 And there's a lot of edge cases in it.
0:24:43 And we don't really trust it.
0:24:45 Like our company doesn't use it and
trust it because we investigated
0:24:48 a bunch of these edge cases and
they're sort of like underspecified.
0:24:52 I don't believe that they're
consistently implemented across browsers.
0:24:56 And we've even had people like on browser
teams like recommend that we don't use it.
0:24:59 You have to figure out a way to
deal with the fact that You have
0:25:02 this persistent storage, right?
0:25:04 And one tab can update and the
other tab cannot be updated.
0:25:07 And then what happens?
0:25:09 Right?
0:25:09 And There's always a problem
with these kind of systems of
0:25:12 like schema migrations, right?
0:25:13 You have to figure out schema migrations,
but it's harder on the web because you
0:25:17 have schema migration on the server
You have schema migration on the client
0:25:20 But then you have the problem that one
tab can update and like want to migrate
0:25:24 the schema forward to like the version
of the Storage that it wants, but the
0:25:28 other tab is like still back on the old
version, you know, like what does it do?
0:25:31 So these are just like
fun practical problems.
0:25:34 So I would actually love to learn a
little bit more about either of those.
0:25:38 And so are those challenges that you've
been facing and that you can fully take
0:25:44 care of on behalf of an application
developer, are you able to like go some
0:25:49 way, but still leave some of the hard.
0:25:52 trade offs to an application developer
and there's some path, some like bad
0:25:57 or even worse trade offs someone needs
to make as an application developer,
0:26:01 they ultimately have to choose.
0:26:04 So how we're able to work around those?
0:26:06 My view is that in order for storage
to be widely used on the web, it
0:26:11 has to be as easy as, easier than
like building a normal web app.
0:26:16 It has to be easier than
building today's web app, right?
0:26:18 And I think that we can get there and
the and the people who need to fill that
0:26:22 gap, who need to make it easier than
today's web apps are library developers.
0:26:26 Like, it's not gonna be browser
vendors because they move way too slow.
0:26:29 Like, it's gonna be library developers
because we have this , awesome
0:26:32 ecosystem of people furiously tr trying
different things to figure this out.
0:26:37 So we have completely solved the cross
tab thing, and I think our solution
0:26:40 to it is, I'm really proud of it.
0:26:42 Like we put a lot of work into it.
0:26:44 It's for this like tiny moment when your
app is updating we put this massive amount
0:26:47 of effort into this, like 10 seconds
at worst when your app is updating and
0:26:52 like two tabs have different versions
but we made it really like elegant.
0:26:56 And like, you don't
have to think about it.
0:26:58 Like basically what happens is
as a developer constructor for
0:27:03 Replicache, you specify the version
of the database that you want.
0:27:06 And that's an identifier that you choose.
0:27:08 So you say like, I want version
seven and you can create as many
0:27:11 different schema versions as you want
in Replicache, and they'll each be
0:27:14 isolated from each other, fully isolated.
0:27:16 And when we talk to the server, we
send in the request the version of the
0:27:21 schema that we're asking on behalf of.
0:27:23 So the server has to respond with
that version or say, I can't serve
0:27:26 that version, you need to reload.
0:27:27 But then internally to deal with that
moment when tabs are on different schema
0:27:32 versions, we actually fork the database
and we have both running at the same time.
0:27:37 So typically in Replicache,
the storage is shared, right?
0:27:41 So you make changes in one tab and
you see them instantly in the other
0:27:44 tab whether you're online or not.
0:27:45 But for this moment, when a schema
update is happening, they fork.
0:27:48 So the tabs can continue independently
and they can continue working.
0:27:51 You know, a concern is like, if you're
typing in a, in an input, you don't
0:27:54 want to just reload the app at that
moment to get the new code, right?
0:27:56 The user could lose their work
or just be frustrated, right?
0:27:59 So you want, you need to allow
the app to continue running for a
0:28:02 little while until it thinks that
it's the right time to update.
0:28:06 That sounds incredible.
0:28:07 And that sounds like
an absolute nightmare.
0:28:09 If like I, as an application developer,
it's hard enough to ship the app
0:28:15 version that I have, and then to even
like really think about that there
0:28:19 is this point of time where a user
has the old version up and running.
0:28:23 And to then just like throw multiple
tabs into the mix here as well.
0:28:28 So, I think whatever pain you
can take away from my application
0:28:32 developer here is amazing.
0:28:34 So yeah you've been mentioning the various
app schema versions and that does at
0:28:39 least locally speaking forks the database.
0:28:42 And I suppose then there's some mechanism
how the forks are eventually being.
0:28:48 joined or merged again, or how if the
different tabs are still being used,
0:28:55 how did those forks come together again?
0:28:57 Well, what happens is they're both
still talking to the same server, right?
0:29:01 So the they're local storage
forks but they're still talking
0:29:04 to a shared truth on the server.
0:29:06 And the server and when tab a makes a
request to the server, it says like,
0:29:10 hi, I, I want to talk and I'm talking
schema version seven and when tab
0:29:15 B sends a request to the server, he
says, I'm talking version eight and
0:29:18 the server can choose to speak both
versions if it wants, or it can choose
0:29:22 to tell seven, I can't talk to you.
0:29:23 I only know version eight but
that doesn't mean that tab seven
0:29:26 has to reload at that moment.
0:29:27 Tab seven can continue working
without a server connection, right?
0:29:30 Because it's local first.
0:29:32 And then it can decide to
reload when it's ready.
0:29:34 Let's say we have tab a and tab
B and they're happily working
0:29:39 in the same version right now.
0:29:41 Is there some communication mechanism
between those two tabs that that
0:29:45 doesn't rely on the server alone?
0:29:48 Yeah, under normal circumstances,
the storage is shared.
0:29:51 So you make changes in tab.
0:29:53 If you're off totally offline
with Replicache or reflect,
0:29:56 and you make changes in tab
a, you will see them in tab B.
0:29:58 They share storage, right?
0:30:00 It's just at this moment when an
upgrade happens, they fork momentarily.
0:30:04 Just to maintain like integrity of the
system, like, so that you don't have.
0:30:09 The schema changing
underneath one of the tabs.
0:30:11 And, you know, that is like a little bit
of a rough edge in the like, abstraction.
0:30:17 You know?
0:30:18 But, under normal circumstances, you're
never going to notice this as a developer.
0:30:22 And it's like, the cleanest
solution that we could come up with.
0:30:24 I agree.
0:30:25 I think it's not like that you're
rolling out a new release constantly.
0:30:29 I think the, still the majority
of the time where the app is being
0:30:32 used, that you're not upgrading.
0:30:35 And so for that little period of
time to have a simpler solution to
0:30:39 this very gnarly problem, sounds
like a very good move to me.
0:30:44 So in the case where it's not
currently upgrading, you mentioned
0:30:47 that those two different tabs.
0:30:50 Share storage.
0:30:51 Does that mean they share the same
IndexedDB database or is there even more
0:30:56 sharing, such as like sharing an array
buffer between those tabs, or what is
0:31:01 the communication mechanism between those?
0:31:03 Are you listening to changes in
IndexedDB, is there sort of like
0:31:08 a broadcast channel between those?
0:31:10 How does the tap interplay work?
0:31:13 I'm so glad you're asking these questions.
0:31:14 Like, I don't know if our listeners
will care about these details.
0:31:17 I hope they do.
0:31:18 Because this is like,
the fun part, you know?
0:31:20 But Yeah, this gets to another one of
the practical challenges that I am proud
0:31:23 of in our implementation that I, that
we put a lot of work into, which is
0:31:26 like we, it was very important to us.
0:31:29 And I know important to you too.
0:31:30 And a lot of other people in this space
that you have 60 frames per second
0:31:33 interactivity, like at, you know, that we
want people to be able to use Replicache
0:31:38 as if it's memory, you know, as if it's
your, as if it's your state model, like
0:31:42 one of the benefits that should come
out of adopting these tools is that you
0:31:44 don't need complex state management
libraries, you know, you have this like
0:31:48 database locally You should be able to
use that as your as your state but when
0:31:52 you look at that from like again from
like an engineering perspective, it's
0:31:55 actually not so easy because You know
storage local storage on SSD is fast.
0:32:01 Sure You know SQLite is fast IDB is
not fast, but you can like wrap it and
0:32:06 do things to it to make it fast but
it's nowhere near as fast as memory.
0:32:09 It's not 60 frames per second.
0:32:10 It's an order of magnitude slower, right?
0:32:12 So, so how do you bridge that gap, right?
0:32:15 And if you want to have cross tab
consistency, if part of the product design
0:32:19 is that you make changes in tab A and
they reflect in tab B, then you cannot
0:32:24 use storage alone as your communication
mechanism because it's too slow, right?
0:32:28 So you have to have memory inside the
tabs at some level, you have to have
0:32:31 memory like that has the state in the
tabs because that's the only way it can
0:32:34 be fast enough and then you again have a
synchronization problem like a distributed
0:32:38 system problem between the tabs, right?
0:32:40 They're changing independently.
0:32:41 So how do you resolve that?
0:32:43 There's like different, I think there's
different legitimate ways to address
0:32:45 this, but the way that we do it, which
is that we basically, we use the storage
0:32:49 as like, We, we run in memory, Replicache
runs in memory, like in the JavaScript
0:32:53 thread, in the main thread, right?
0:32:55 So it's right there next to your app.
0:32:57 It's crazy fast and it lazily
loads and stores to IDB.
0:33:02 And we have a, basically a
synchronization protocol between the
0:33:04 tabs which you can kind of think
of it roughly as like two Replicache
0:33:09 browsers, like sync via the server
and two Replicache tabs sync by IDB.
0:33:13 That's like the basic structure.
0:33:15 And yes, we need to have a way to know
when something has changed cross tabs.
0:33:18 And for that, we use broadcast channel.
0:33:21 But like, you know, it's the same
if you're familiar at all with
0:33:23 Replicache, the server doesn't
send data proactively to the client.
0:33:27 The server only sends a poke
that like a tap on the shoulder
0:33:30 that something has changed and
the client requests the changes.
0:33:33 And we kind of do the
same thing cross tab.
0:33:35 Like we, we use broadcast channel to
tell the other tab, Hey, IDB has changed.
0:33:39 And then.
0:33:40 That tab is like running as fast
as it can in memory and it has like
0:33:43 a background process to refresh
itself from storage periodically.
0:33:47 I'm very curious to learn more about
that background process as well.
0:33:52 Are you leveraging workers at all in
your implementation here, or is this
0:33:57 mostly running in the main thread?
0:33:59 And this is where given that you
have multiple tabs, multiple main
0:34:02 threads is most of Replicache
running in the main threads.
0:34:06 We don't use workers as part
of the implementation of
0:34:09 Replicache Currently at all.
0:34:11 you know, we, We want people to be able
to use Replicache as if it's memory,
0:34:15 it should be as fast as memory and, the
only way to do that is to be memory, you
0:34:19 know, you could have something running
in another thread, in another worker,
0:34:22 but then you're still gonna have to have
state and memory, right, so, What we
0:34:26 landed on was, we have Replicache as a
in, like an in memory main thread thing.
0:34:33 It has a background process that syncs
with IDB, but that is just like a periodic
0:34:37 task that's running on the main thread.
0:34:39 You can easily run Replicache
in a worker, and many people do.
0:34:42 People, like, people do
this to do full text search.
0:34:45 They run Replicache in another tab, they
do, you know, indexing in that, or they
0:34:50 run it in a worker, they do indexing
in that worker, and then they, like,
0:34:52 access that index from the main thread.
0:34:54 And because of the cross tab communication
that we have, it works fine across workers
0:34:58 too, workers in the main thread, you know,
but where to put workers in your stack is
0:35:03 like a, is a, is an application developer
question not a Replicache question
0:35:09 I think it's very possible that
we would implement workers.
0:35:11 We would add workers to various parts
of the implementation of Replicache,
0:35:15 like as an implementation detail, you
know, like there's some background
0:35:18 tasks that we need to do, like cleaning
up things, you know, that are heavy.
0:35:21 And it would be useful to have those
on a background thread to make sure
0:35:24 they don't interfere with the UI.
0:35:27 The one thing that like people
frequently ask, and it has come up over,
0:35:31 over the development of Replicache,
whether to use service workers.
0:35:35 and because it, it seems so tempting.
0:35:39 It's like this shared place that you
can run code, you know, across tabs.
0:35:42 But man, service workers are like
another part of the web platform.
0:35:45 That's just so hard to use.
0:35:46 You know, it's just so gnarly,
and I feel like almost nobody
0:35:49 knows how to use them, you know?
0:35:51 And like, there's so few examples
of them being used successfully.
0:35:54 And if we use service workers in
Replicache, it would have impact
0:35:57 on how people build their apps.
0:35:58 So we just haven't gone there.
0:36:00 Once you're just a little library that
you use in your JavaScript app, then
0:36:05 I think that keeps things way simpler
since I think very few JavaScript
0:36:09 developers are even aware of the
concept of a thread in the context
0:36:14 of building like their React app.
0:36:16 And so a worker is a thread, but once
you have a library or technology,
0:36:20 that spans, the main thread that spans
workers or service workers, then you
0:36:25 need to conceptually deal with that.
0:36:27 But it also becomes a tooling
and a bundling problem.
0:36:31 So this is where I think the best
technology that we have for those sorts
0:36:35 of patterns right now would be Vite
0:36:38 and my opinion
0:36:39 so have you had success or not so much
success with certain technologies?
0:36:45 We love Vite it's like my default.
0:36:48 It's kind of a funny story, like, when
I started RociCorp which was, like I
0:36:52 said now, almost four years ago I wasn't
up to date with like the web, like,
0:36:56 and like the popular open source tools.
0:36:59 And my friend was like,
you gotta check out Next.
0:37:02 js, it's like, so awesome,
like, you guys should figure
0:37:05 out how to integrate with Next.
0:37:05 js, and like, I started, like, working
with it, and I was like, oh, this is
0:37:08 like a really cool DX, but like, I'm
trying to, like, what is it, like,
0:37:11 what's the core value here, I couldn't
put my finger on it, like, it's like,
0:37:14 it's hosting, like, there's the the
thing where you have deploys that are
0:37:18 like, like, preview deploys, that's
really cool, but like, is that, I'm
0:37:20 trying to think, like, why is this so
exciting, and I finally realized, it's
0:37:24 like, the easiest way to set up React.
0:37:26 That's really like the back then, like
that's the core of it, you know, that's
0:37:29 how like it's like setting up a react
project is just so hard, like, and then
0:37:34 I, you know, I think V has taken the
has taken the crown on that front now,
0:37:39 Yeah, I think, so my take is that if
you're using Next and typically you
0:37:43 then deploy it on Vercel, I think that's
great for like anything that's like
0:37:48 a more on the, if there's a spectrum
from website to web app, then I think
0:37:53 this is rather where you start on the
website spectrum and make it more,
0:37:57 add more and more app like features.
0:38:00 But I think it becomes increasingly
hard if you want to build a
0:38:04 local first app with Next.
0:38:06 js as you want to introduce those
capabilities, as you want to introduce
0:38:10 really deep storage mechanisms or
once you want to work with workers.
0:38:14 I'm sure it's on their roadmap somewhere.
0:38:17 But I think they, they've just started
their journey on one side of the spectrum,
0:38:21 which is, I think, rather to the websites.
0:38:24 And that's great and
that works really well.
0:38:26 Server side rendering, React server
components is great for this use case.
0:38:31 But I think once you want to build web
apps that really feel more, almost like a
0:38:37 native app, I think this is where you need
to reach for a different tooling stack.
0:38:41 And I'm currently very happy with
Vite as it has support for workers
0:38:46 as a first class citizen, was a
bit rough over the last few years.
0:38:49 But it has gotten a lot better with every
release and I'm very happy using it.
0:38:55 And I've even seen a few libraries
also shipping workers out of the
0:38:59 box that work quite well with Vite
0:39:02 so an example here would
be the SQLite WASM built.
0:39:05 That also ships with some workers out
of the box, which works pretty well,
0:39:11 yeah we use it often and like it as well.
0:39:14 I don't have as much experience
with workers in particular just
0:39:17 because we haven't taken it on as
like an implementation detail yet.
0:39:20 But yeah, just overall we have a lot of
success with using it for our samples.
0:39:24 And like, you know, when you're
building this kind of stuff, you end
0:39:26 up making apps all the time, right?
0:39:28 So speaking of maybe
this is a good segue to.
0:39:32 How I would use Replicache or reflect
in, in my, let's say in my React app.
0:39:39 So I think you've been mentioning MobX.
0:39:42 Is that a typical technology that you
use Replicache with, or does Replicache
0:39:48 completely replace something like MobX?
0:39:51 MobX, Redux, Zustand, all those all
those sort of state technologies.
0:39:56 Are they complimentary or are they
rather being replaced by Replicache?
0:40:02 I think long, like long term they're
being replaced but the reality is
0:40:06 that Replicache isn't there yet.
0:40:07 Like these are, you know, very well
developed, like sophisticated tools,
0:40:11 you know, like that people have,
Developed, like to do legitimately
0:40:15 hard things, you know, like, you have
a fairly large data set in memory and
0:40:19 you're trying to update like little
bits of it reactively, you know, that's
0:40:21 like a legitimately hard problem.
0:40:23 And so Replicache has an API like A
subscription, API that's memory fast.
0:40:28 And I think it actually competes
well with like SQ lite based systems.
0:40:32 In many cases it's faster.
0:40:34 But.
0:40:35 I mean, if you're building something
like Dax is building, you know, that
0:40:38 has like a lot of data in it like 30,
000, 50, 000 records, you know, and,
0:40:43 you know, you're trying to do 60 frames
per second updates in there, and you
0:40:46 have a lot of, like, computation, like,
derived computation chains in memory,
0:40:50 like, we don't have the, we don't have
the APIs in Replicache yet that, that can
0:40:54 compete with, like, MobX or, like, Signia
from TLDraw, like, things like that.
0:41:00 And the cool thing is like, the
design of Replicache is complementary
0:41:03 to putting those things on top.
0:41:04 Like at the bottom of the Replicache
abstraction stack, you have a
0:41:07 key value store that's reactive.
0:41:09 You know, so you can like plug those
reactive changes, like, into your into
0:41:12 Zustand or whatever, and it'll work great.
0:41:15 It's interesting, like, different people
in the space started at different angles.
0:41:18 Like, I think that's something
you've been passionate about,
0:41:19 like, from the very beginning.
0:41:21 There's so many exciting things
happening in local first.
0:41:23 Like, other people have
started focusing there.
0:41:25 We started, like, a lot more on making
the synchronization correct and robust.
0:41:29 And making partial sync
work, authorized sync work.
0:41:31 You know, making the mass
storage, like, really fast.
0:41:34 And we still have to like finish up
the libraries legitimately, like the
0:41:37 API layer to make it really nice.
0:41:39 I think that it's going to be competitive
with like using those types of
0:41:42 tools, like, you know, next quarter.
0:41:43 Yeah.
0:41:44 I mean, Replicache has been, I think,
one of the first solutions really been
0:41:49 on the local first market in that way.
0:41:53 And so, and I think you, you have
been quite ahead there in terms of
0:41:57 the work on syncing and just having a.
0:42:01 A fully fledged thing out there that
developers can use to build on top of and
0:42:06 that shows I think most most of the local
first apps that have been built over the
0:42:11 past one or two years, I think, use your
technology and I think that's already.
0:42:16 driving some of the change that
I want to see for our apps.
0:42:20 So are there some apps that that
you're particularly excited about,
0:42:25 where you say, okay, this is
exactly what I wanted to help create
0:42:29 more of or help create more of?
0:42:31 Well, I mean, right now the
one that, that I'm like most
0:42:34 excited about probably is sst.
0:42:36 dev, Dax's thing that I've
mentioned a few times.
0:42:39 Like just because, I don't
know it's an example of like a
0:42:43 data intensive application that
is like public that you can try.
0:42:46 A lot of our, a lot of our customers
are like, you know, they're private
0:42:49 things that, you know, not easy
for people to access outside.
0:42:52 And yeah, we have a lot of.
0:42:56 Customers using Replicache for things
that are like in the building industry
0:42:59 or like service industry where like,
like we have a customer that is building
0:43:03 like a tool that people who build
houses like would use and, you know,
0:43:08 they go out in the field and there's
intermittent connectivity and, you
0:43:11 know, actually like building a house
is like a super data intensive thing.
0:43:15 You know, there's like
thousands of elements on the
0:43:17 checklist to a house, you know?
0:43:19 And like lots of people that have to
come through and look at it and then
0:43:21 there's back office things that happen
and like, so it's like a perfect use
0:43:24 case, but it's not something that you
can like use, you know, that you could
0:43:28 go try and use right now because,
you know, it's a private system.
0:43:31 So yeah, I think like sst.
0:43:32 dev is like the best example
right now that I'm excited about.
0:43:36 I'm equally excited about the things that
I can use myself, as well as the anecdotes
0:43:41 I'm hearing about other technologies
being created for other people.
0:43:46 So I think this is what I'm particularly
excited about Local First, that it
0:43:52 makes it easier to build technologies
for use cases that were just not that
0:43:58 Viable before to, to build technologies
with the tools that we had before.
0:44:02 So what you've been sharing about
the construction use case here, or
0:44:07 you've been also privately sharing
a few other use cases with me,
0:44:10 those sounds, sound incredible.
0:44:12 And this is exactly why I'm
excited that local first opens