1
00:00:00,000 --> 00:00:01,100
There's  database.

2
00:00:01,451 --> 00:00:03,721
sync engines and then there's
document sync engines.

3
00:00:04,161 --> 00:00:07,131
So for database sync engine, I think
of things like Linear, like things

4
00:00:07,131 --> 00:00:11,641
where you have some relational
model data, you probably don't

5
00:00:11,641 --> 00:00:12,881
want the client to have all of it.

6
00:00:12,881 --> 00:00:16,924
You kind of have, the client
storing some subset of a database

7
00:00:16,924 --> 00:00:18,679
for each, for each account.

8
00:00:18,909 --> 00:00:22,639
Maybe you're sharing this data across
multiple people in that account.

9
00:00:22,946 --> 00:00:27,209
On the document sync side you're sending
all of the data down to the client.

10
00:00:27,281 --> 00:00:31,428
The unit of data that gets synced
is in memory size on the browser.

11
00:00:31,428 --> 00:00:33,238
You're not dealing with like
a terabyte of data here.

12
00:00:33,281 --> 00:00:34,441
you're not taking a subset of it.

13
00:00:34,441 --> 00:00:35,911
You're synchronizing the entire document.

14
00:00:36,451 --> 00:00:41,028
This would be kind of things like Figma
or Google Docs, where there's a full local

15
00:00:41,028 --> 00:00:44,838
copy of some self standing piece of data.

16
00:00:45,251 --> 00:00:47,351
Welcome to the localfirst.fm podcast.

17
00:00:47,711 --> 00:00:51,701
I'm your host, Johannes Schickling and I'm
a web developer, a startup founder, and

18
00:00:51,701 --> 00:00:53,651
love the craft of software engineering.

19
00:00:53,921 --> 00:00:57,836
For the past few years, I've been on a
journey to build a modern, high quality

20
00:00:57,836 --> 00:01:01,811
music app using web technologies, and
in doing so, I've been falling down the

21
00:01:01,811 --> 00:01:03,611
rabbit hole of local-first software.

22
00:01:04,061 --> 00:01:06,941
This podcast is your invitation
to join me on that journey.

23
00:01:07,736 --> 00:01:11,636
In this episode, I'm speaking to
Paul Butler, founder of Jamsocket,

24
00:01:11,756 --> 00:01:13,646
and creator of the Y-Sweet Project.

25
00:01:14,096 --> 00:01:17,576
In this conversation, we talk about
building versus buying a sync engine

26
00:01:17,906 --> 00:01:22,686
and explore the various projects behind
Jamsocket, including Plane, Y-Sweet,

27
00:01:22,706 --> 00:01:27,996
and Forever VM Before getting started,
also a big thank you to ElectricSQL

28
00:01:28,016 --> 00:01:30,266
and Jazz for supporting this podcast.

29
00:01:30,446 --> 00:01:32,246
And now my interview with Paul.

30
00:01:33,451 --> 00:01:35,661
Hey, Paul, so nice to
have you on the podcast.

31
00:01:35,671 --> 00:01:36,291
How are you doing?

32
00:01:37,031 --> 00:01:37,401
I'm good.

33
00:01:37,401 --> 00:01:38,041
Thank you, Johannes.

34
00:01:38,041 --> 00:01:40,271
I'm excited to be here and been
listening since the beginning.

35
00:01:41,034 --> 00:01:41,974
Thank you so much.

36
00:01:42,004 --> 00:01:45,114
The two of us had the pleasure
to meet in person at last year's

37
00:01:45,114 --> 00:01:48,744
local-first conf, and I'm hoping
to see you there again this year.

38
00:01:49,174 --> 00:01:50,834
So for those in the audience.

39
00:01:51,079 --> 00:01:53,959
Who don't know who you are, would
you mind introducing yourself?

40
00:01:54,719 --> 00:01:55,009
Sure.

41
00:01:55,009 --> 00:01:56,039
I'm Paul Butler.

42
00:01:56,039 --> 00:01:58,469
I'm a co founder of a
company called Jamsocket.

43
00:01:58,622 --> 00:02:03,512
the kind of one line pitch is it's
like a Lambda, but for WebSockets.

44
00:02:03,865 --> 00:02:04,265
Yeah.

45
00:02:04,305 --> 00:02:06,855
I've been looking a little
bit into Jamsocket and it's

46
00:02:06,895 --> 00:02:08,805
like, looks really fascinating.

47
00:02:08,815 --> 00:02:13,095
And I also want to hear more about The
origin story where it's coming from,

48
00:02:13,375 --> 00:02:17,825
since by now we got more and more
sort of like infrastructural options.

49
00:02:17,825 --> 00:02:21,125
Obviously there's like
CloudFlare with their primitives,

50
00:02:21,125 --> 00:02:22,545
CloudFlare workers, et cetera.

51
00:02:22,895 --> 00:02:27,585
And I think with Jamsocket, you
provide a really powerful alternative.

52
00:02:27,885 --> 00:02:30,085
For high scale applications.

53
00:02:30,385 --> 00:02:35,095
So yeah, before we go into more into
depth, what Jamsocket is and what

54
00:02:35,095 --> 00:02:38,909
it offers, would you mind sharing
a bit more of the origin story,

55
00:02:38,939 --> 00:02:40,879
how you ended up working on it?

56
00:02:41,355 --> 00:02:41,665
Sure.

57
00:02:41,665 --> 00:02:41,895
Yeah.

58
00:02:41,895 --> 00:02:45,106
so I started, with my co founder started
the company about three years ago.

59
00:02:45,352 --> 00:02:49,892
prior to that, I was working in finance
and I was doing a lot of building a lot of

60
00:02:49,892 --> 00:02:52,512
internal tools for myself, my team, that.

61
00:02:52,882 --> 00:02:56,972
We're dealing with midsize amounts of
data, so talking about like single digit,

62
00:02:56,972 --> 00:03:02,182
double digit, gigabytes of data, not
anything that was out of realm of putting

63
00:03:02,182 --> 00:03:06,432
in RAM for a desktop application, but I
realized that as soon as people wanted

64
00:03:06,432 --> 00:03:09,362
these things to be delivered through
the browser, there was really nowhere

65
00:03:09,362 --> 00:03:13,149
to put that data, that I couldn't really
load that over the Internet into the

66
00:03:13,159 --> 00:03:17,467
browser, Chrome would just give up,
didn't really make sense to load that

67
00:03:17,487 --> 00:03:21,547
into kind of a flask server or something
like that, because the web stack is

68
00:03:21,547 --> 00:03:26,524
kind of built for these servers to not
consume a lot of memory for each user

69
00:03:26,524 --> 00:03:28,281
of the application, things like that.

70
00:03:28,281 --> 00:03:33,301
So I really wanted this sort of neutral
location and a way for the, I almost

71
00:03:33,301 --> 00:03:34,951
think of it as a way for a browser.

72
00:03:35,196 --> 00:03:39,256
Based application to spin up
a server side sub process that

73
00:03:39,266 --> 00:03:40,966
just belongs to that browser tab.

74
00:03:40,986 --> 00:03:45,166
And that when you close that browser tab,
that server side process also goes away.

75
00:03:45,676 --> 00:03:48,406
So that was essentially the
origin story of Jamsocket.

76
00:03:48,786 --> 00:03:52,136
That makes a lot of sense, but could
you motivate a little bit more?

77
00:03:52,136 --> 00:03:54,666
What kind of application
I should imagine there?

78
00:03:54,666 --> 00:03:57,946
I've never worked in finance
and I think the average web

79
00:03:57,946 --> 00:03:59,896
developer has sort of like.

80
00:04:00,151 --> 00:04:05,687
A list of like 50 Airbnb,
items that they want to render.

81
00:04:05,687 --> 00:04:09,607
And then there's like pagination and
all of that easily fits like in a

82
00:04:09,877 --> 00:04:15,879
JSON array that you can fetch into
like, a single, CRUD, REST API call.

83
00:04:16,092 --> 00:04:20,992
But when you say like single digits,
double digit, gigabytes of data, what

84
00:04:20,992 --> 00:04:23,012
sort of data are we dealing with here?

85
00:04:23,042 --> 00:04:27,142
And if you want it to transfer it
over the wire into the browser,

86
00:04:27,342 --> 00:04:28,872
what would that even look like?

87
00:04:28,892 --> 00:04:33,622
Would that be sort of like one big
JSON blob or can't, yeah, maybe

88
00:04:33,622 --> 00:04:35,072
you can motivate that a bit more.

89
00:04:35,557 --> 00:04:40,064
Yeah, so, one of the motivating examples
at the time was, we would run like a

90
00:04:40,064 --> 00:04:41,924
simulation, a back test simulation.

91
00:04:41,924 --> 00:04:46,944
So we have some model that we hypothesize
is predictive of of stock returns,

92
00:04:47,347 --> 00:04:52,577
run it back in time and generate a
bunch of data could be say on every

93
00:04:52,577 --> 00:04:55,857
five minute increment or even more
fine grained than that, over petabytes

94
00:04:55,857 --> 00:04:58,094
and petabytes of, past market data.

95
00:04:58,550 --> 00:05:03,270
and then we get back some gigantic
time series data, number of time

96
00:05:03,270 --> 00:05:07,117
series, maybe you have profit and
loss over time and record of all

97
00:05:07,117 --> 00:05:08,847
the trades and everything like that.

98
00:05:08,874 --> 00:05:14,174
so we have like massive, not
massive, large, like, Gigabyte,

99
00:05:14,370 --> 00:05:18,150
multi gigabyte of time series data,
likely in something like Parquet.

100
00:05:18,304 --> 00:05:20,724
that tend to be the best
format for that type of thing.

101
00:05:21,140 --> 00:05:24,530
and so over the wire, ideally
it would be Parquet or Arrow.

102
00:05:25,130 --> 00:05:25,580
Got it.

103
00:05:25,670 --> 00:05:28,730
And over that sort of
data you want to do like.

104
00:05:28,960 --> 00:05:34,484
Based on the user's input through the UI,
driving some sort of queries, some sort

105
00:05:34,484 --> 00:05:40,334
of like accumulations to make sense of
like what the data is trying to tell us.

106
00:05:40,744 --> 00:05:41,194
Yeah.

107
00:05:41,194 --> 00:05:44,784
It was things like, maybe I want to be
able to drill down in the data, in the

108
00:05:44,784 --> 00:05:50,620
client, be able to kind of go from this
high level overview of data to kind of.

109
00:05:51,065 --> 00:05:54,862
Looking at specific trades,
specific stocks, things like that.

110
00:05:55,245 --> 00:05:55,625
Got it.

111
00:05:55,965 --> 00:06:01,492
And sort of your insight and way to deal
with that, fundamental problem where

112
00:06:01,492 --> 00:06:07,262
like ideally you could just like move
that big data blob over in front of like

113
00:06:07,262 --> 00:06:12,235
your, browser that you're looking at
and then like happily query and compute

114
00:06:12,235 --> 00:06:17,365
away, but that wasn't feasible because
like Chrome or another browser has.

115
00:06:17,600 --> 00:06:22,330
Certain limits and the way how you
want it to like, cope with that

116
00:06:22,380 --> 00:06:25,980
is to say like, okay, we're going
to have like a little companion.

117
00:06:25,990 --> 00:06:30,260
Each browser session has a little
companion on some beefy server, which

118
00:06:30,270 --> 00:06:32,730
holds all of that data in memory.

119
00:06:33,230 --> 00:06:34,750
And then there's some sort of like.

120
00:06:34,950 --> 00:06:41,497
Real time wire protocol that helps
you do that, like still so fast that

121
00:06:41,497 --> 00:06:43,744
it's, sort of proxying to being local.

122
00:06:44,504 --> 00:06:45,534
Yeah, exactly that.

123
00:06:45,534 --> 00:06:48,284
I kind of think of it as like a
somewhere along the spectrum where

124
00:06:48,284 --> 00:06:49,644
you have like there's thin client.

125
00:06:50,274 --> 00:06:53,174
Sort of setups where the server does
everything and the client's really

126
00:06:53,174 --> 00:06:58,684
just a dumb display all the way to a
full fledged browser based app that

127
00:06:59,004 --> 00:07:01,914
where everything's happening in the
browser that can happen in the browser.

128
00:07:02,244 --> 00:07:05,174
I think there's some middle
ground where you get.

129
00:07:05,484 --> 00:07:10,624
Next frame latency on almost
everything, but maybe in the background

130
00:07:11,334 --> 00:07:14,024
it needs to query some server
data and load that in and maybe it

131
00:07:14,024 --> 00:07:15,814
can even approximate client side.

132
00:07:16,110 --> 00:07:18,970
what that next frame will look
like, but it's able to sort of do

133
00:07:18,970 --> 00:07:20,080
that in the background as well.

134
00:07:20,324 --> 00:07:20,704
Got it.

135
00:07:20,984 --> 00:07:26,644
So as you face those problems that has
led you to get so interested in the

136
00:07:26,644 --> 00:07:31,264
problem that you started to dedicate
your next chapter in life to that.

137
00:07:31,564 --> 00:07:35,404
And that led to you building
a technology called Plane.

138
00:07:35,744 --> 00:07:38,544
And that was then also the
foundation for Jamsocket.

139
00:07:38,554 --> 00:07:43,444
So can you explain a bit more
what Plane does and then how it

140
00:07:43,484 --> 00:07:45,364
connects to what Jamsocket is?

141
00:07:45,724 --> 00:07:48,157
Yeah, so, and just to kind
of continue on the story.

142
00:07:48,157 --> 00:07:51,327
So my co founder, Taylor was at
data dog and had kind of faced

143
00:07:51,327 --> 00:07:52,577
some, some similar problems.

144
00:07:52,587 --> 00:07:55,057
So we got together in 2022.

145
00:07:55,490 --> 00:07:58,680
and the first thing we started
working on was, yeah, what became

146
00:07:58,680 --> 00:08:01,057
Plane, which is, it's open source.

147
00:08:01,164 --> 00:08:06,774
and it's a, I think of it as kind of
the way that we spin up those processes.

148
00:08:06,774 --> 00:08:10,735
It's kind of the orchestration plane
essentially for that type of application.

149
00:08:11,232 --> 00:08:15,819
so what it's responsible for is you
kind of give it a pool of computers.

150
00:08:16,275 --> 00:08:20,445
you tell it you want to start a specific
process and it will find where on those

151
00:08:20,485 --> 00:08:22,065
on that pool of computers to start that.

152
00:08:22,715 --> 00:08:28,025
But it will also give that process
a secure web accessible URL.

153
00:08:28,335 --> 00:08:32,475
so it can give it a host name and
a kind of a password, essentially,

154
00:08:32,755 --> 00:08:35,679
then anything on the web,
anything on the public Internet.

155
00:08:35,930 --> 00:08:39,560
That can access the web, can
use that URL to send and receive

156
00:08:39,590 --> 00:08:41,660
messages from that process.

157
00:08:42,330 --> 00:08:45,700
And as long as there's at least
one open connection to that

158
00:08:45,700 --> 00:08:47,220
process, Plane will keep it alive.

159
00:08:47,240 --> 00:08:50,390
And then as soon as there's
no more processes, Plane

160
00:08:50,390 --> 00:08:51,560
will start a countdown timer.

161
00:08:51,640 --> 00:08:54,170
And if nothing reconnects,
it'll shut that process off.

162
00:08:54,785 --> 00:08:55,145
Got it.

163
00:08:55,615 --> 00:09:01,065
So in terms of use cases, you've clearly
motivated that original use case that you

164
00:09:01,075 --> 00:09:04,072
had while working, at a financial company.

165
00:09:04,459 --> 00:09:09,279
are those also the kind of use cases that,
you know, mostly face when talking to

166
00:09:09,279 --> 00:09:14,549
people that are interested in Jamsocket
or is there a wider set of applications

167
00:09:14,599 --> 00:09:16,789
that Jamsocket is trying to serve.

168
00:09:17,185 --> 00:09:20,585
yeah, largely not that actually
hasn't, we haven't seen that many

169
00:09:20,585 --> 00:09:25,600
use cases of kind of wanting to just
modify massive data sets or deal with

170
00:09:25,600 --> 00:09:26,790
massive data sets in the browser.

171
00:09:27,460 --> 00:09:31,170
But one of the things we quickly realized
was that the infrastructure we were

172
00:09:31,190 --> 00:09:35,910
building had a lot of parallels to
how Figma did things, how Google Docs

173
00:09:35,910 --> 00:09:38,880
did things, how a lot of these kind of
collaborative applications did things.

174
00:09:39,300 --> 00:09:45,020
And so we decided to kind of lean into
the sync engine hosting side of things.

175
00:09:45,392 --> 00:09:45,832
Got it.

176
00:09:45,892 --> 00:09:49,499
And when I'm looking at your,
website, among a few other

177
00:09:49,499 --> 00:09:54,122
companies, it looks like Rayon is
built also on, on top of Jamsocket.

178
00:09:54,122 --> 00:09:57,512
So I've happened to have seen their
launch, I think, a while back.

179
00:09:57,879 --> 00:10:03,149
if I recall correctly, it was sort of
like a really interesting Figma esque,

180
00:10:03,425 --> 00:10:05,755
application, I think for architects.

181
00:10:06,245 --> 00:10:10,779
And, yeah, maybe you can share a little
bit more about their specific scenario,

182
00:10:10,789 --> 00:10:15,179
how they're employing Jamsocket to
build their collaborative experience.

183
00:10:15,509 --> 00:10:17,899
Yeah, Rayon's one of
my favorite use cases.

184
00:10:17,932 --> 00:10:19,042
cause we've really grown with them.

185
00:10:19,160 --> 00:10:22,210
They've been using us since we
started the company, essentially.

186
00:10:22,314 --> 00:10:26,124
they were one of the first users on the
platform and we've seen them kind of grow

187
00:10:26,124 --> 00:10:27,414
as they launched and, and everything.

188
00:10:27,890 --> 00:10:32,660
essentially the way that they're using
us is that we are the data backend for

189
00:10:32,780 --> 00:10:34,070
these documents while they're open.

190
00:10:34,250 --> 00:10:39,027
So I open a document, you open a
document, they'll start a server

191
00:10:39,237 --> 00:10:41,007
on Jamsocket for that document.

192
00:10:41,397 --> 00:10:42,267
And as I make edits.

193
00:10:43,117 --> 00:10:44,547
They get pushed up to that server.

194
00:10:45,077 --> 00:10:46,417
They get sent back down to you.

195
00:10:46,427 --> 00:10:50,927
And, that back end is also
what's storing the data on S3.

196
00:10:51,457 --> 00:10:56,980
So even if it's single player mode, that
Jamsocket server still sits between their

197
00:10:56,980 --> 00:11:01,455
end user and the source of truth on the
data source, the durable data source.

198
00:11:02,012 --> 00:11:02,452
Okay.

199
00:11:02,612 --> 00:11:06,622
So you mentioning S3 and
a durable data source.

200
00:11:06,855 --> 00:11:11,475
maybe we can take a step back
and motivate if someone wants to

201
00:11:11,475 --> 00:11:16,105
build their own, little version of
something like Jamsocket or Plane.

202
00:11:16,402 --> 00:11:17,872
how would that look like?

203
00:11:17,872 --> 00:11:22,182
So there seems to be something
pretty beefy in the middle that

204
00:11:22,222 --> 00:11:25,032
holds the necessary data in memory.

205
00:11:25,632 --> 00:11:30,072
And as the name, as in memory
suggests, that's pretty volatile.

206
00:11:30,372 --> 00:11:34,062
So if someone stumbles over a power
cord, that data might be gone.

207
00:11:34,682 --> 00:11:39,545
And, that's also why it needs to stay some
more, more durable, something like S3.

208
00:11:39,915 --> 00:11:43,552
So can you walk us through
like the rough architecture?

209
00:11:43,922 --> 00:11:48,662
And what were sort of like the insides and
deliberate trade offs that went into it?

210
00:11:49,082 --> 00:11:53,835
Yeah, I mean, a common pattern that I
see people use with Jamsocket is that the

211
00:11:53,835 --> 00:11:58,455
source of truth for application data will
kind of shift as the application is used.

212
00:11:58,465 --> 00:12:04,465
So at rest, the source of truth of the
application data is In durable storage

213
00:12:04,465 --> 00:12:09,215
somewhere, usually S3, something like
that, where you might want to, might

214
00:12:09,215 --> 00:12:13,675
not want to write to that like 60
times a second, but you want it to

215
00:12:13,675 --> 00:12:16,345
persist when that document is open.

216
00:12:16,745 --> 00:12:20,995
Then that source of truth effectively of
that document is in memory on Jamsocket.

217
00:12:21,575 --> 00:12:23,965
And the nice thing about that
is it's, you know, it's memory.

218
00:12:23,975 --> 00:12:25,625
You can write to it very frequently.

219
00:12:25,635 --> 00:12:28,845
You can write to it 100 times a
second if you want to more than that.

220
00:12:29,129 --> 00:12:32,859
and that can then be synced down to
all of the connected clients and then.

221
00:12:33,179 --> 00:12:37,259
In some sort of loop or, you could
have some sort of write ahead log, but

222
00:12:37,359 --> 00:12:40,949
as changes are made to that document,
you are then durably persisting them.

223
00:12:41,332 --> 00:12:43,902
some people really care about
that being really low latency.

224
00:12:44,019 --> 00:12:47,742
I think in general, unless it's
really a bad thing for users to lose

225
00:12:47,742 --> 00:12:52,792
like 5 seconds of data that just
batching everything up into writing

226
00:12:53,222 --> 00:12:54,882
just the edits every five seconds.

227
00:12:54,932 --> 00:12:56,512
Something like that is pretty reasonable.

228
00:12:56,819 --> 00:13:00,949
or you can, you know, what a lot of people
do is they just say 60 seconds is fine.

229
00:13:00,979 --> 00:13:04,769
I'm just going to write the entire
document over what existed there before

230
00:13:04,819 --> 00:13:10,699
every 60 seconds because the outage, you
know, a server just failing out of the

231
00:13:10,699 --> 00:13:12,089
blue is actually pretty rare these days.

232
00:13:12,410 --> 00:13:12,820
Got it.

233
00:13:13,100 --> 00:13:19,457
So if we compared to, a technology
like Cloudflare durable objects, with

234
00:13:19,477 --> 00:13:25,234
Cloudflare workers, that's a particularly
distinct programming model where it

235
00:13:25,234 --> 00:13:28,814
kind of gives you kind of Best of
both worlds in that regard that you

236
00:13:28,854 --> 00:13:34,044
only pay for the CPU cycles where you
actually want the CPU to do things.

237
00:13:34,414 --> 00:13:39,704
And otherwise it can hibernate while still
keeping a web socket connection alive, for

238
00:13:39,704 --> 00:13:46,504
example, or keep like some memory alive or
rehydrated from some persistent storage.

239
00:13:46,887 --> 00:13:50,797
is that sort of like a useful
parallel way to think about

240
00:13:50,807 --> 00:13:52,767
the programming model and also.

241
00:13:53,095 --> 00:13:59,935
can I implement any sort of free web
socket messages or request handlers, or is

242
00:13:59,955 --> 00:14:07,685
there a more pre specified API, something
like Redis, how I interact with data from

243
00:14:07,685 --> 00:14:09,585
a client to the server and vice versa?

244
00:14:09,902 --> 00:14:10,762
Yeah, good question.

245
00:14:10,814 --> 00:14:14,734
I agree that like, I think durable
objects is probably the closest kind of

246
00:14:14,834 --> 00:14:17,124
parallel product out there right now.

247
00:14:17,734 --> 00:14:22,814
when we started this up, durable objects,
wasn't really a big thing and had may have

248
00:14:22,814 --> 00:14:24,164
existed, but had a lot of limitations.

249
00:14:24,260 --> 00:14:27,124
like, I think we, we came at things
from a very different angle, but kind of

250
00:14:27,124 --> 00:14:29,974
landed in a similar architectural space.

251
00:14:30,237 --> 00:14:35,042
in terms of the servers though, we
just, Really host anything that's HTTP.

252
00:14:35,052 --> 00:14:38,205
So, when I talk about it as being
for WebSocket servers, I think that

253
00:14:38,425 --> 00:14:42,375
we kind of came at it at an angle
of we want this to be the right

254
00:14:42,385 --> 00:14:44,045
model for hosting WebSocket servers.

255
00:14:44,075 --> 00:14:48,232
But, and we do, you know,
we sit on the connection.

256
00:14:48,232 --> 00:14:48,832
So we.

257
00:14:49,442 --> 00:14:52,552
Work well with WebSockets where
there's a long lived connection,

258
00:14:52,562 --> 00:14:56,022
because then we know not to terminate
the server with HTTP requests.

259
00:14:56,022 --> 00:14:57,932
We have to rely a little
bit more on heuristics.

260
00:14:58,255 --> 00:15:00,315
we've got that WebSocket connection open.

261
00:15:00,775 --> 00:15:05,082
really, just anything could be Socket.IO
could be, your own WebSocket protocol.

262
00:15:05,354 --> 00:15:07,745
we essentially just take a
container from our customers that

263
00:15:07,805 --> 00:15:10,015
will serve HTTP on port 8080.

264
00:15:10,415 --> 00:15:13,837
And we expose that to the, the outside
web through a proxy that we wrote.

265
00:15:14,420 --> 00:15:14,780
Got it.

266
00:15:14,790 --> 00:15:20,957
So in the specific case of Rayon, did they
build their own from scratch sync engine?

267
00:15:20,967 --> 00:15:26,667
Did they leverage any specific off the
shelf technology, something like Yjs?

268
00:15:26,894 --> 00:15:31,084
given that Jamsocket advertises as
the platform where you build your

269
00:15:31,084 --> 00:15:35,760
own sync engine on top of, maybe you
can walk us through by this example.

270
00:15:36,060 --> 00:15:37,330
how I should think about that.

271
00:15:37,970 --> 00:15:38,550
Yeah.

272
00:15:38,600 --> 00:15:41,680
they're one of a number of customers
who have kind of built their own

273
00:15:41,680 --> 00:15:43,770
sync engine on top of Jamsocket.

274
00:15:44,007 --> 00:15:46,717
there's not like an SDK that you
need to adopt or anything like

275
00:15:46,717 --> 00:15:48,557
that on, on the server side.

276
00:15:48,557 --> 00:15:50,797
It's, you're just writing a web server.

277
00:15:51,044 --> 00:15:54,024
but one of the things that's
specific about this model is that.

278
00:15:54,594 --> 00:16:00,274
You are guaranteed by the infrastructure
that only one, at most one server is

279
00:16:00,274 --> 00:16:05,904
running per document or however, you want
to fragment your kind of space of things,

280
00:16:06,314 --> 00:16:08,016
but, in their case, it's per document.

281
00:16:08,016 --> 00:16:13,006
And so, yeah, you get that guarantee
from the system, and then it becomes much

282
00:16:13,006 --> 00:16:14,726
easier to implement your own sync engine.

283
00:16:14,726 --> 00:16:19,366
But we, at least at the Jamsocket
level, are not opinionated about how

284
00:16:19,366 --> 00:16:21,046
you actually go about implementing that.

285
00:16:21,362 --> 00:16:22,119
but then you mentioned Y-Sweet.

286
00:16:22,139 --> 00:16:23,354
Yeah, we.

287
00:16:23,864 --> 00:16:27,841
So Rayon does not use Y Suite, but, some
of our customers use Y Suite, which is a

288
00:16:27,891 --> 00:16:29,951
Yjs backend that we wrote that we provide.

289
00:16:29,951 --> 00:16:32,331
That's a much more opinionated
path if they want to take that.

290
00:16:32,744 --> 00:16:33,124
Got it.

291
00:16:33,144 --> 00:16:33,464
Yeah.

292
00:16:33,474 --> 00:16:36,834
I want to learn a lot more about
Y Suite in a moment as well.

293
00:16:37,164 --> 00:16:42,804
But given that you've already mentioned
those 2 paths of Y Suite, which is a

294
00:16:42,834 --> 00:16:47,838
off the shelf technology that you're
building that basis, on top of Yjs,

295
00:16:47,858 --> 00:16:53,254
which is a very well known, CRDT
implementation, probably the most, common

296
00:16:53,284 --> 00:16:55,691
and, longest technology that's out there.

297
00:16:55,961 --> 00:16:59,391
so that being an example for
an off the shelf technology.

298
00:16:59,641 --> 00:17:02,711
Rayon, which has built
their own sync engine.

299
00:17:03,034 --> 00:17:07,241
you've probably seen many, many,
decisions being made where people

300
00:17:07,261 --> 00:17:11,681
choose to use an off the shelf
technology or choose to build their own.

301
00:17:11,948 --> 00:17:14,908
which sort of advice would you
give to people who are thinking

302
00:17:14,918 --> 00:17:19,148
whether they should buy, or, as
an alternative to buying is like

303
00:17:19,148 --> 00:17:21,148
adopting an off the shelf technology.

304
00:17:22,378 --> 00:17:24,418
Yeah, I think that where.

305
00:17:25,038 --> 00:17:29,918
It kind of comes down to for the kind
of build versus off the shelf is whether

306
00:17:29,918 --> 00:17:34,048
you want to have business logic live
in the sync engine on the server side.

307
00:17:34,364 --> 00:17:38,664
so where I think you generally don't
need that is if you want to just

308
00:17:38,684 --> 00:17:43,824
think text documents, things like
that, where CRDTs are probably the

309
00:17:43,824 --> 00:17:48,244
best way to do it right now, at least
the most off the shelf way to do it.

310
00:17:48,639 --> 00:17:51,199
You can do your own way, but
it's sort of a research problem.

311
00:17:51,686 --> 00:17:54,606
where, on the other hand, I think
if you have a very simple data

312
00:17:54,606 --> 00:17:57,516
model, but you want to do atomic
transactions, you want to have, kind

313
00:17:57,516 --> 00:17:59,586
of an event sourcing type approach.

314
00:17:59,926 --> 00:18:04,176
you want to be able to do things
like trees with reparenting and

315
00:18:04,206 --> 00:18:08,468
and some of that Ends up being that
you're working against the CRDT.

316
00:18:08,698 --> 00:18:12,208
and in those cases, I think it
makes more sense to implement

317
00:18:12,208 --> 00:18:13,108
your own business logic.

318
00:18:13,398 --> 00:18:16,938
The other thing that we see is if
maybe you want some change to trigger

319
00:18:16,938 --> 00:18:19,438
some action server side, you want
actions to have some side effect.

320
00:18:19,438 --> 00:18:21,984
You want to, maybe some piece
of data changes and you want

321
00:18:21,984 --> 00:18:23,204
to insert that into a queue.

322
00:18:23,534 --> 00:18:26,214
So it becomes really nice to
have some server side code that

323
00:18:26,214 --> 00:18:28,214
Reacts to changes to the document.

324
00:18:28,658 --> 00:18:30,148
that's another place that we find.

325
00:18:30,588 --> 00:18:33,658
Building your own tends to be
really nice because you can just

326
00:18:34,408 --> 00:18:38,068
have that be one server that's
responsible both for the sync and,

327
00:18:38,068 --> 00:18:40,178
and for triggering some side effect.

328
00:18:40,901 --> 00:18:45,291
Right so maybe to linger a little
bit on that specific point, I think

329
00:18:45,301 --> 00:18:50,224
with, local-first software you have,
in this scenario where you build your

330
00:18:50,224 --> 00:18:54,004
own sync engine, you have kind of two,
approaches, how to deal with that.

331
00:18:54,004 --> 00:18:57,984
And also for the off the shelf
approach, if you use something like Yjs.

332
00:18:58,666 --> 00:19:02,216
so if you build your own, you can
basically just wherever you handle the

333
00:19:02,216 --> 00:19:06,663
messages, you can, possibly inspect
the messages and see, okay, this

334
00:19:06,663 --> 00:19:09,673
seems to be like a user signup event.

335
00:19:09,943 --> 00:19:14,803
And so here let's send out that
confirmation email or something like that.

336
00:19:15,309 --> 00:19:19,669
but another approach could also be
that you basically have a server

337
00:19:19,669 --> 00:19:25,909
side client instance that listens
to the same sync messages and you.

338
00:19:25,984 --> 00:19:30,888
Based on the state that you have,
on that server side client, you

339
00:19:30,888 --> 00:19:33,568
could then basically React to that.

340
00:19:33,924 --> 00:19:37,344
have you thoughts on one
approach versus the other?

341
00:19:37,394 --> 00:19:44,314
Maybe, one is like a lot more, expensive
to run or, more, complex to model.

342
00:19:44,521 --> 00:19:47,228
What thoughts do you have on
the different approaches here?

343
00:19:47,681 --> 00:19:50,771
I think that where I've tended to see
this breakdown because we've, we've seen

344
00:19:50,771 --> 00:19:56,008
it both ways and we've seen, we've seen
customers do it both ways is that if it's.

345
00:19:56,413 --> 00:19:58,683
Purely just sort of
Reacting to a side effect.

346
00:19:58,693 --> 00:20:02,623
And it's something that you want to
that your model of it is that it's

347
00:20:02,623 --> 00:20:05,173
like a server triggered type of thing.

348
00:20:05,183 --> 00:20:07,873
Like, if it's that, you know,
that send email example, send

349
00:20:07,873 --> 00:20:08,913
some sort of notification.

350
00:20:09,259 --> 00:20:13,619
I think that that makes more sense
to just do in the server, just in

351
00:20:13,619 --> 00:20:15,089
terms of architectural complexity.

352
00:20:15,333 --> 00:20:16,623
you could certainly listen for the events.

353
00:20:16,623 --> 00:20:20,923
And if there's architectural reasons that
that makes sense for you, I don't see

354
00:20:20,923 --> 00:20:26,868
any problems with it, but where I think
that the server being a client can make a

355
00:20:26,868 --> 00:20:32,354
lot of sense is like AI integration type
things, where you want the server in this

356
00:20:32,354 --> 00:20:36,024
case that, you know, it's code running
on the server, but it, your application

357
00:20:36,034 --> 00:20:37,944
should just treat it like another client.

358
00:20:38,384 --> 00:20:40,844
This is something like maybe an
agent's going out and modifying

359
00:20:40,844 --> 00:20:42,224
a document based on some prompt.

360
00:20:42,657 --> 00:20:45,967
Then I think it does make sense if
you want to run it through the same

361
00:20:46,957 --> 00:20:51,067
kind of code paths that a user edit
would go through, then it makes

362
00:20:51,067 --> 00:20:55,157
sense to, to kind of treat that
as a distinct client of the data.

363
00:20:55,484 --> 00:20:55,854
Got it.

364
00:20:55,874 --> 00:21:03,317
So to dig a little bit more and towards
that, server as a client, when I'm

365
00:21:03,367 --> 00:21:08,487
thinking more about like a browser
client, or like using my, phone,

366
00:21:08,897 --> 00:21:14,054
or there's like a concrete point in
time where I'm starting a session.

367
00:21:14,084 --> 00:21:15,154
I'm opening a tab.

368
00:21:15,154 --> 00:21:16,154
I'm opening an app.

369
00:21:16,464 --> 00:21:18,224
I'm doing things afterwards.

370
00:21:18,224 --> 00:21:19,304
Like I'm closing it.

371
00:21:19,314 --> 00:21:22,224
So there's like a concrete start stop.

372
00:21:22,484 --> 00:21:26,477
Maybe there's like some background
stuff, but, let's pretend there's just

373
00:21:26,477 --> 00:21:29,207
like a clear start, stop 30 seconds.

374
00:21:29,557 --> 00:21:30,267
And that's it.

375
00:21:30,647 --> 00:21:34,517
how should I think about
that in a server context?

376
00:21:34,785 --> 00:21:38,324
let's say I'm trying to offer
that to a thousand customers.

377
00:21:38,634 --> 00:21:42,944
Would I have a thousand separate,
like, but let's go crazy.

378
00:21:42,944 --> 00:21:46,934
Let's say we have a thousand
VMs, one per customer.

379
00:21:47,324 --> 00:21:49,334
that strikes me as very expensive.

380
00:21:49,334 --> 00:21:54,244
So what is like a useful programming
model, like a useful deployment model.

381
00:21:54,539 --> 00:21:57,632
To, deploy those sort
of server side clients.

382
00:21:57,980 --> 00:22:01,880
so the way that Jamsocket does
this is that we run a process

383
00:22:01,880 --> 00:22:04,117
for every service, essentially.

384
00:22:04,117 --> 00:22:07,357
So when, when you and I are connected
to a document, we're running a

385
00:22:07,357 --> 00:22:11,294
process, not a full fledged VM, but
it's, using some Cisco interception

386
00:22:11,294 --> 00:22:12,344
through something called G visor.

387
00:22:12,344 --> 00:22:14,554
So it's a little bit more
secure than sort of just.

388
00:22:14,554 --> 00:22:14,619
Yeah.

389
00:22:15,219 --> 00:22:16,239
Containerized workloads.

390
00:22:16,699 --> 00:22:20,829
so the nice thing about that is that
processes are pretty good at giving

391
00:22:20,829 --> 00:22:24,092
resources back to the system when
they're, when they're not actively in use.

392
00:22:24,102 --> 00:22:28,663
So we've seen is that when you want
the server to kind of first Okay.

393
00:22:29,383 --> 00:22:32,833
Class of interactions where it's
sort of definitely want it to

394
00:22:32,843 --> 00:22:34,133
be processed by the service.

395
00:22:34,386 --> 00:22:36,516
in those cases, it makes
sense to run directly in the

396
00:22:36,516 --> 00:22:38,486
sync engine when it comes to.

397
00:22:38,733 --> 00:22:42,229
multiple clients, we tend to
see those run off of Jamsocket.

398
00:22:42,239 --> 00:22:47,629
So these are running on an end user
server talking to Jamsocket and the

399
00:22:47,629 --> 00:22:54,259
pattern that I've seen their work is
that client will maybe trigger something

400
00:22:54,259 --> 00:22:58,089
directly through like a web endpoint on
that remote server that's not running

401
00:22:58,089 --> 00:23:02,899
on Jamsocket, that server will then talk
to Jamsocket to say, fetch some data or,

402
00:23:03,213 --> 00:23:05,283
connect and sort of trigger something.

403
00:23:05,519 --> 00:23:08,536
so it might synchronize data,
but it's not, a long live client.

404
00:23:08,556 --> 00:23:12,406
It's kind of a client that spun
up based on a specific action.

405
00:23:12,726 --> 00:23:14,086
That's usually triggered by the client.

406
00:23:14,516 --> 00:23:14,836
Got it.

407
00:23:14,856 --> 00:23:15,826
That makes a lot of sense.

408
00:23:15,836 --> 00:23:19,916
So instead of like being super
long running, and that's times

409
00:23:19,936 --> 00:23:25,066
and for each possible instance,
you make it more event based.

410
00:23:25,076 --> 00:23:29,076
So, let's say there is a new sync
message that you want to React

411
00:23:29,086 --> 00:23:31,656
to, or there's like some other.

412
00:23:31,916 --> 00:23:37,106
maybe like a webhook that's coming in
from Stripe and then, so you, you do your

413
00:23:37,106 --> 00:23:43,643
thing as a response to the event and, then
you go, yield again, back to the runtime.

414
00:23:44,026 --> 00:23:47,896
and I think a model that also
comes to mind that could fit

415
00:23:47,906 --> 00:23:49,166
really well together here.

416
00:23:49,476 --> 00:23:54,043
Is, our durable long running
workflows, something like Temporal.

417
00:23:54,053 --> 00:23:57,813
And there's also other options as
well, I think could work really well

418
00:23:57,813 --> 00:24:00,133
together here that you have a workflow.

419
00:24:00,873 --> 00:24:05,323
That's essentially a participant
in a sync system where it's

420
00:24:05,323 --> 00:24:07,293
just a long running workflow.

421
00:24:07,333 --> 00:24:12,073
It's just like another client happens to
live on a server and not in a browser.

422
00:24:12,386 --> 00:24:17,636
yeah, I'm, I'm really excited to see more
folks explore this since I think it will.

423
00:24:17,910 --> 00:24:21,705
open the door for a whole bunch of
different application topologies, really.

424
00:24:22,048 --> 00:24:26,135
One of the things, things that we found
with Y Suite is that, we had people ask

425
00:24:26,135 --> 00:24:28,565
for, like, I want a Python client to this.

426
00:24:28,585 --> 00:24:30,165
And it was for exactly that reason.

427
00:24:30,165 --> 00:24:34,365
Like they want to run some server side
code that interacts with a document.

428
00:24:34,825 --> 00:24:36,535
same with the node on the node side.

429
00:24:37,070 --> 00:24:40,240
We support kind of the built in
WebSocket client in the browser, but

430
00:24:40,240 --> 00:24:44,270
we also support a shimmed in WebSocket
client so that you can run it in Node.

431
00:24:45,043 --> 00:24:45,713
Very cool.

432
00:24:45,753 --> 00:24:49,993
Yeah, I'm really looking forward to
like, whether it's Python or well,

433
00:24:50,160 --> 00:24:55,678
I'm a native person in JavaScript and
JavaScript has this amazing, Aspect to

434
00:24:55,678 --> 00:25:00,478
it that supposedly runs everywhere and
we're getting more and more there with

435
00:25:00,478 --> 00:25:03,805
like ESM now, being really, the default.

436
00:25:03,885 --> 00:25:09,178
And, I'm really excited about bringing
the same business logic, the same code

437
00:25:09,408 --> 00:25:11,598
to all sorts of different platforms.

438
00:25:11,948 --> 00:25:14,013
And I think sync engines are.

439
00:25:14,247 --> 00:25:19,177
or like a huge lever that gets us closer
towards that since like, otherwise

440
00:25:19,177 --> 00:25:24,223
we can have, the code there, but if
we don't have the data there, that

441
00:25:24,263 --> 00:25:26,773
is only good for so many use cases.

442
00:25:27,383 --> 00:25:28,223
So maybe.

443
00:25:28,383 --> 00:25:32,163
transitioning towards Y-Sweet,
what you've already mentioned.

444
00:25:32,567 --> 00:25:37,357
before we get into what Y-Sweet
is, can you share more about

445
00:25:37,367 --> 00:25:42,137
the origin story of Y-Sweet and
which problems you try to solve?

446
00:25:42,540 --> 00:25:42,910
Yeah.

447
00:25:42,973 --> 00:25:46,910
so we'd already been working on Jamsocket
for a while by the time we started Y-Sweet

448
00:25:46,930 --> 00:25:50,417
and we sort of started to see for one
thing, You know, we thought from the

449
00:25:50,417 --> 00:25:53,467
get go that, well, people are going to
want to write their own sync engines.

450
00:25:53,843 --> 00:25:57,043
one of the things we saw was that a
lot of people were sort of using Yjs

451
00:25:57,043 --> 00:26:03,143
and other CRDTs and running those on
Jamsocket and finding advantages, even

452
00:26:03,143 --> 00:26:08,263
though they don't need the authoritative
kind of model of Jamsocket that they were

453
00:26:08,263 --> 00:26:10,273
still finding advantages to having that.

454
00:26:10,680 --> 00:26:14,550
so we started thinking like, what
would a Yjs server kind of built

455
00:26:14,560 --> 00:26:16,000
to run on Jamsocket look like?

456
00:26:16,000 --> 00:26:17,050
And one of the things that.

457
00:26:17,855 --> 00:26:20,385
It's nice if we're, you know,
running a lot of a process is that

458
00:26:20,385 --> 00:26:22,055
it's really memory lightweight.

459
00:26:22,055 --> 00:26:26,225
So we wrote Y-Sweet in Rust and
it's pretty memory efficient.

460
00:26:26,578 --> 00:26:30,448
another thing that we became really
opinionated about is that you shouldn't

461
00:26:30,458 --> 00:26:32,588
really start document data in a database.

462
00:26:32,648 --> 00:26:33,778
I think it's just a bad fit.

463
00:26:33,828 --> 00:26:37,638
I think with something like a, you
know, if you're building something

464
00:26:37,638 --> 00:26:40,388
like Figma, like Figma uses S3.

465
00:26:40,678 --> 00:26:44,908
As where they store the document, they
store the document metadata in Postgres

466
00:26:44,938 --> 00:26:49,938
and started to see a lot of use cases
of like patterns like that, because if

467
00:26:49,938 --> 00:26:54,160
you're writing the document each document
that's open many times a minute, If

468
00:26:54,160 --> 00:26:57,140
you're using a Postgres database, that
Postgres database is in the bottleneck.

469
00:26:57,210 --> 00:26:59,160
Every, every edit is coming through that.

470
00:26:59,480 --> 00:27:03,310
Whereas S3 is a more distributed
kind of file system where if you

471
00:27:03,320 --> 00:27:07,820
have a server that is the authority
of what's in a document at that

472
00:27:07,820 --> 00:27:11,890
given point in time, it can just
write to S3 and you can horizontally

473
00:27:11,890 --> 00:27:13,130
scale that out as much as you want.

474
00:27:13,150 --> 00:27:16,580
So we kind of became opinionated
about, okay, that should be rust.

475
00:27:16,580 --> 00:27:17,320
It should be lightweight.

476
00:27:17,360 --> 00:27:18,520
It should write to S3.

477
00:27:18,880 --> 00:27:20,410
and it should be, Okay.

478
00:27:20,783 --> 00:27:25,057
As simple as possible to just use, like,
I really like software like Caddy, where

479
00:27:25,067 --> 00:27:28,297
it is, which is web server written in Go,
if people aren't familiar with it, where

480
00:27:28,297 --> 00:27:31,417
you like that has really sane defaults.

481
00:27:31,477 --> 00:27:34,967
It's somewhat opinionated
about just doing things right.

482
00:27:34,967 --> 00:27:35,997
You don't have to

483
00:27:35,997 --> 00:27:36,627
fantastic.

484
00:27:36,627 --> 00:27:41,933
It even gives you like, SL certificates
that work locally works with tail scales.

485
00:27:41,933 --> 00:27:42,563
Fantastic.

486
00:27:42,563 --> 00:27:43,423
Definitely check it out.

487
00:27:43,423 --> 00:27:44,603
If you're not using it yet.

488
00:27:45,143 --> 00:27:50,453
Yeah, so Caddy just like simplifies so
much and just like does things right.

489
00:27:50,463 --> 00:27:52,793
And so we wanted to build a piece
of software that was felt like

490
00:27:52,793 --> 00:27:56,143
that to use, that it was, we wanted
something that you could use in a

491
00:27:56,143 --> 00:28:01,093
CICD process and it would be the same
API as if you were using it at scale,

492
00:28:01,413 --> 00:28:03,013
horizontally scaled out on the cluster.

493
00:28:03,053 --> 00:28:06,073
so it was like, because the other thing,
I mean, the things that we were thinking

494
00:28:06,073 --> 00:28:11,758
about at the time were like, what would
an open source document sync engine

495
00:28:11,758 --> 00:28:16,762
look like, if we were to write it from
scratch and we kind of kept landing on,

496
00:28:17,632 --> 00:28:22,002
it would look something like, you know,
pretty close to Yjs, even if we didn't

497
00:28:22,012 --> 00:28:25,292
have the distributed constraints of Yjs.

498
00:28:25,698 --> 00:28:28,408
So we're like, well, Yjs exists.

499
00:28:28,408 --> 00:28:29,938
It has great community.

500
00:28:30,493 --> 00:28:31,983
Great people involved with it.

501
00:28:32,423 --> 00:28:34,223
this looks like what
we would want to build.

502
00:28:34,223 --> 00:28:36,783
So let's just build a
sync engine around this.

503
00:28:37,293 --> 00:28:37,683
Got it.

504
00:28:37,973 --> 00:28:43,270
In terms of the, behavior or like what
makes it a little bit more like Caddy

505
00:28:43,290 --> 00:28:48,357
in terms of opinionated, but like,
very well motivated opinions baked

506
00:28:48,357 --> 00:28:50,987
into it, if you compare it to the Yjs.

507
00:28:51,267 --> 00:28:56,820
Default server, any sort of thing that
stands out there where you lean a little

508
00:28:56,820 --> 00:28:59,100
bit more heavy into some opinions?

509
00:28:59,490 --> 00:29:03,400
Yeah, I mean, I think the default Yjs
server is built to be very modular

510
00:29:03,400 --> 00:29:08,412
and suit a bunch of use cases The Yjs
community in general embraces this

511
00:29:08,412 --> 00:29:10,802
idea of providers where a provider.

512
00:29:10,882 --> 00:29:15,732
So Yjs itself is just a data structure and
then providers are what will synchronize

513
00:29:15,732 --> 00:29:18,782
it to another client or synchronize
it to a database or things like that.

514
00:29:19,075 --> 00:29:22,605
the kind of official
way to do things in the.

515
00:29:22,955 --> 00:29:25,975
Yjs world is to kind of compose
a bunch of providers together.

516
00:29:26,242 --> 00:29:29,782
so you might have an index db provider on
the client, synchronizing the index db.

517
00:29:30,182 --> 00:29:34,142
You might have a web socket provider,
synchronizing to other clients.

518
00:29:34,602 --> 00:29:36,842
And then you might have a
database provider on the server.

519
00:29:37,232 --> 00:29:41,642
We wanted to just have a single stack
that was kind of our opinionated stack.

520
00:29:41,642 --> 00:29:44,892
So we have an index db
implementation on the client.

521
00:29:45,332 --> 00:29:49,122
We have our s3 storage, which we've
Decided is, you know, the only storage

522
00:29:49,692 --> 00:29:52,562
that will support will support S3
compatible storage, but it's, it's

523
00:29:52,562 --> 00:29:57,982
ultimately our opinion was object storage
is the right way to do storage for this.

524
00:29:58,302 --> 00:30:00,392
and then we have our, our
wire protocol as well.

525
00:30:00,402 --> 00:30:00,862
WebSocket.

526
00:30:01,489 --> 00:30:01,939
Got it.

527
00:30:02,029 --> 00:30:02,749
That makes sense.

528
00:30:02,929 --> 00:30:03,149
Yeah.

529
00:30:03,149 --> 00:30:05,744
And I haven't managed yet to.

530
00:30:05,744 --> 00:30:10,407
Have, Kevin Jans here on the podcast,
but he happens to also live in Berlin,

531
00:30:10,437 --> 00:30:14,710
and I've just seen him, for the, last
local-first meetup that we've done here.

532
00:30:14,980 --> 00:30:20,294
So I think it's, well, about time that
we hear from Kevin, about YJS, there's

533
00:30:20,294 --> 00:30:26,439
been, it's been such a rich ecosystem
of different things around it, so I

534
00:30:26,469 --> 00:30:28,204
think we gotta make that happen as well.

535
00:30:28,654 --> 00:30:29,454
Yeah, you should.

536
00:30:29,454 --> 00:30:33,834
So I'm actually, I've been procrastinating
editing a podcast that I did with Kevin.

537
00:30:33,914 --> 00:30:34,904
so we'll have that soon.

538
00:30:35,684 --> 00:30:36,224
There you go.

539
00:30:36,277 --> 00:30:37,777
we should put it in the show notes.

540
00:30:38,227 --> 00:30:45,000
So, YJS  you've built, just, as you've
seen that this is a, flavor of Sync

541
00:30:45,000 --> 00:30:48,440
server that can be hosted on, Jamsocket.

542
00:30:48,820 --> 00:30:55,480
So, is my understanding correct that, if
I want to use YJS with Y Suite, I can just

543
00:30:55,480 --> 00:30:58,140
deploy that off the shelf on Jamsocket

544
00:30:59,390 --> 00:31:00,990
yeah, so you could deploy that.

545
00:31:01,280 --> 00:31:04,240
We have like a off the shelf offering
that deploys it on Jamsocket.

546
00:31:04,620 --> 00:31:07,060
you can run it on your
own servers as well.

547
00:31:07,137 --> 00:31:10,540
and it's one of the things we decided
was like, regardless of how it's

548
00:31:10,540 --> 00:31:12,310
hosted, it should be the same API.

549
00:31:12,310 --> 00:31:15,870
So we have kind of the, what I call
it, the document management API where

550
00:31:15,870 --> 00:31:19,640
you're, you know, create a document, give
somebody an access token to that document.

551
00:31:19,777 --> 00:31:22,567
that is sort of just universal,
no matter how it's deployed.

552
00:31:22,977 --> 00:31:28,077
Got it, so I think Yjs is one of the
most mature options right now for

553
00:31:28,077 --> 00:31:32,047
people who want to build local-first
apps, for people who are just, who've

554
00:31:32,047 --> 00:31:36,924
heard it a bunch of times, but maybe
haven't yet come around to, fully.

555
00:31:37,264 --> 00:31:38,784
Implement their app using it.

556
00:31:39,134 --> 00:31:42,634
what are questions that
people should ask themselves?

557
00:31:42,634 --> 00:31:47,134
Whether Yjs is a useful foundation
for the app and in which scenarios

558
00:31:47,154 --> 00:31:50,804
would you say, actually, you probably
want to build your own sync engine.

559
00:31:51,204 --> 00:31:54,434
yeah, so I, I think the, one of the
first dimensions to think about here is

560
00:31:54,434 --> 00:31:56,474
I see this sort of, there's two worlds.

561
00:31:56,474 --> 00:31:58,224
There's like database.

562
00:31:58,575 --> 00:32:00,845
sync engines and then there's
document sync engines.

563
00:32:01,285 --> 00:32:04,255
So for database sync engine, I think
of things like Linear, like things

564
00:32:04,255 --> 00:32:08,765
where you have some relational
model data, you probably don't

565
00:32:08,765 --> 00:32:10,005
want the client to have all of it.

566
00:32:10,005 --> 00:32:14,049
You kind of have, the client
storing some subset of a Database

567
00:32:14,049 --> 00:32:15,804
for each, for each account.

568
00:32:16,034 --> 00:32:19,764
Maybe you're sharing this data across
multiple people in that account.

569
00:32:20,034 --> 00:32:25,484
database sync world where there's,
Elastic SQL and, zero and, power sync

570
00:32:25,484 --> 00:32:27,844
and kind of a number of players there.

571
00:32:28,298 --> 00:32:31,137
instant DB and triplet
and a number of others.

572
00:32:31,784 --> 00:32:36,837
on the document sync side, that's
where you kind of have, you're sending

573
00:32:36,847 --> 00:32:38,157
all of the data down to the client.

574
00:32:38,157 --> 00:32:41,054
So you're dealing with kind of
the unit of data that gets synced

575
00:32:41,064 --> 00:32:43,590
is in memory size on the browser.

576
00:32:43,590 --> 00:32:45,400
You're not dealing with like
a terabyte of data here.

577
00:32:45,444 --> 00:32:46,604
you're not taking a subset of it.

578
00:32:46,604 --> 00:32:48,074
You're synchronizing the entire document.

579
00:32:48,614 --> 00:32:51,990
This would be kind of things
like Figma or Google Docs, where

580
00:32:52,160 --> 00:32:54,170
there's a full local copy of.

581
00:32:54,530 --> 00:32:57,000
Some self standing piece of data.

582
00:32:57,480 --> 00:33:00,440
and generically in, Yjs,
that's essentially like a

583
00:33:00,440 --> 00:33:03,160
JSON style or JSON shape data.

584
00:33:03,540 --> 00:33:07,084
So things like nested maps,
things like nested lists, and

585
00:33:07,084 --> 00:33:10,200
text, and then JSON primitives.

586
00:33:10,584 --> 00:33:15,434
Is it fair to say that, so you've
mentioning Figma, Google Docs, if I think

587
00:33:15,434 --> 00:33:20,717
about Figma and Google Docs, there is
like a distinct boundary of a document.

588
00:33:20,987 --> 00:33:23,417
So I have a Google Docs document open.

589
00:33:23,457 --> 00:33:25,157
I have a Figma document open.

590
00:33:25,575 --> 00:33:32,775
is it wherever a product experience
has sort of like for a given part of

591
00:33:32,775 --> 00:33:38,065
the experience is all centered around
a document or tl draw comes to mind?

592
00:33:38,429 --> 00:33:44,404
is that a great fit for embracing
the document model and anything that

593
00:33:44,444 --> 00:33:49,294
is more, rich in terms of, like a
relational database where you can

594
00:33:49,294 --> 00:33:51,224
just freely join between things.

595
00:33:51,564 --> 00:33:56,334
That's where you would choose the other
approach is that's a useful rule of thumb.

596
00:33:56,777 --> 00:33:57,067
Yeah.

597
00:33:57,067 --> 00:34:00,817
I think the words, that you use distinct
boundary, I think that's really nails it.

598
00:34:00,904 --> 00:34:03,904
a, if there's kind of like a document
with This is like self contained.

599
00:34:04,054 --> 00:34:05,094
It's distinct.

600
00:34:05,274 --> 00:34:08,724
you mentioned TL draw like, and
actually, I mean, I think this gets

601
00:34:08,724 --> 00:34:12,744
to another point is that you can
use both in the same application.

602
00:34:13,074 --> 00:34:17,074
So TL draw uses zero and their
own document sync engine.

603
00:34:17,904 --> 00:34:21,194
Figma has built their
own sync engine for both.

604
00:34:21,657 --> 00:34:23,037
and they're distinct sync engines.

605
00:34:23,382 --> 00:34:24,942
They can be used in tandem as well,

606
00:34:25,405 --> 00:34:29,929
right I mean, that gets us to a really
interesting, topic more generally, which

607
00:34:29,929 --> 00:34:32,499
is combining multiple sync engines.

608
00:34:32,539 --> 00:34:37,549
And I think for people who've been
dabbling in local-first, that might be

609
00:34:37,559 --> 00:34:42,439
more intuitive, but I think for, people
who are just very new to, the local-first

610
00:34:42,459 --> 00:34:47,719
space, it's hard enough to wrap your head
around, choosing the right sync engine.

611
00:34:47,719 --> 00:34:50,889
Now you're telling us, wait,
you should choose multiple.

612
00:34:51,229 --> 00:34:54,712
Can you motivate a little bit more
of like, how to think about that?

613
00:34:55,215 --> 00:34:57,655
so I think of it as like the app
layer and the document layer.

614
00:34:57,685 --> 00:35:00,745
If you have a document based application,
there's, you know, if you have a

615
00:35:00,755 --> 00:35:03,585
file viewer, for example, I think
of that as app layer, you're not in

616
00:35:03,585 --> 00:35:04,905
a specific document at that moment,

617
00:35:05,335 --> 00:35:09,225
like in Figma where I'm on the home
screen and I see my various projects.

618
00:35:09,895 --> 00:35:11,265
Yeah, exactly.

619
00:35:11,338 --> 00:35:16,318
and I think there's nothing that forces
that part to be real time synced.

620
00:35:16,621 --> 00:35:19,631
In a lot of cases, I think a
traditional Postgres database

621
00:35:20,201 --> 00:35:21,351
goes a long way for that.

622
00:35:21,755 --> 00:35:25,895
and then, but then once you're in the
document, that's where I think you, you

623
00:35:25,895 --> 00:35:29,941
do kind of need a sync engine because,
it's the type of thing that if you have

624
00:35:30,031 --> 00:35:33,701
two Google Docs open in two different
tabs, you expect them to be in sync,

625
00:35:33,711 --> 00:35:35,101
even if you're just a single user.

626
00:35:35,473 --> 00:35:38,033
I think that actually motivates
like 98 percent of the value of

627
00:35:38,033 --> 00:35:41,143
local-first is just somebody who
has the same document open in two

628
00:35:41,143 --> 00:35:42,573
tabs and they've got 100 tabs open.

629
00:35:43,086 --> 00:35:48,886
I think that that's less of a given
expectation these days for like a

630
00:35:48,886 --> 00:35:50,406
project view or something like that.

631
00:35:50,406 --> 00:35:52,800
I think that It's a nice
surprise when that is in sync.

632
00:35:52,830 --> 00:35:56,800
And I think it is becoming the status
quo, but I think that overall it's.

633
00:35:57,051 --> 00:36:00,761
less of an expectation that, Oh,
you might have to refresh your Figma

634
00:36:00,761 --> 00:36:06,141
project, to sort of see the new assets
that come up or that kind of thing.

635
00:36:06,568 --> 00:36:10,738
so yeah, but it is, I do think, and
there's been a bit of Twitter debate

636
00:36:10,738 --> 00:36:13,898
about this lately, but like whether
the same sync engine can handle both.

637
00:36:14,271 --> 00:36:18,003
I think that there are things that you are
going to need transactions for, and if you

638
00:36:18,003 --> 00:36:21,890
need transactions, you're going to need a
database with a single that is effectively

639
00:36:21,890 --> 00:36:23,480
a single bottleneck on updates.

640
00:36:23,960 --> 00:36:27,150
At the same time, if you have lots of
documents, you don't want those documents

641
00:36:27,180 --> 00:36:28,850
to be bottlenecked in a single point.

642
00:36:29,290 --> 00:36:33,986
So I think unless there's a solution that
offers both distributed and centralized

643
00:36:33,986 --> 00:36:36,316
with transactions, you kind of need both.

644
00:36:36,735 --> 00:36:37,085
Got it.

645
00:36:37,095 --> 00:36:42,155
So, if you're thinking more about the
leaning into the document aspect of

646
00:36:42,155 --> 00:36:47,558
it, or even, when you say like, that
something is bottleneck, let's say we

647
00:36:47,568 --> 00:36:50,415
also embrace the, database aspect of it.

648
00:36:50,875 --> 00:36:52,335
Maybe you have different.

649
00:36:52,630 --> 00:36:58,280
Workspaces, and, I think there's
still like one aspect of like drawing

650
00:36:58,280 --> 00:37:03,486
boundaries around some body of data,
where you say like, Hey, within

651
00:37:03,496 --> 00:37:08,886
that boundary, I care about certain
constraints, maybe that there shouldn't

652
00:37:08,886 --> 00:37:11,546
be more than 10 documents ever.

653
00:37:11,941 --> 00:37:16,321
Or maybe you want to enforce
some constraints around like

654
00:37:16,411 --> 00:37:18,811
users, access control, et cetera.

655
00:37:19,201 --> 00:37:23,841
can you share any sort of
learnings or advice about how

656
00:37:23,841 --> 00:37:25,921
to approach this entire topic?

657
00:37:25,951 --> 00:37:31,561
Like, how do you decide this is a useful
boundary about like how data should be

658
00:37:31,601 --> 00:37:34,901
modeled at and fragmented or petitioned.

659
00:37:35,371 --> 00:37:39,575
And what are some of the dimensions that
should be taken into consideration here?

660
00:37:40,031 --> 00:37:43,791
So I think in general, if it's
not obvious what a document

661
00:37:43,791 --> 00:37:47,441
should be in an application, then
it's probably the document model

662
00:37:47,441 --> 00:37:49,261
is probably not the right fit.

663
00:37:49,431 --> 00:37:53,188
I think things like Figma where, you know,
you're, in a document at a time, like.

664
00:37:53,763 --> 00:37:55,803
You might have a different
document in another tab, but

665
00:37:55,803 --> 00:37:59,353
you don't have two documents in
the same tab concurrently open.

666
00:37:59,733 --> 00:38:01,223
it's taking up the whole screen.

667
00:38:01,233 --> 00:38:05,593
Like, I think that there's certain
heuristics like that, that just

668
00:38:05,593 --> 00:38:08,793
tell you, like, this is definitely
a document model application.

669
00:38:09,213 --> 00:38:10,893
Same with Google Drive or Google Docs.

670
00:38:11,006 --> 00:38:12,196
you kind of have one thing.

671
00:38:12,511 --> 00:38:13,381
Open at once,

672
00:38:13,851 --> 00:38:15,231
where would you put Linear?

673
00:38:15,261 --> 00:38:21,138
Since you could, for example, put each
Linear issue into its own document.

674
00:38:21,168 --> 00:38:23,678
Why might that be a reasonable approach?

675
00:38:23,745 --> 00:38:24,145
where is this?

676
00:38:24,145 --> 00:38:24,845
Where might have not?

677
00:38:25,531 --> 00:38:27,661
I think I could see.

678
00:38:28,191 --> 00:38:33,361
That being reasonable, if there, if you
really care about the tickets themselves

679
00:38:33,401 --> 00:38:37,751
being, you know, multiple people editing
a ticket at one time and seeing the text.

680
00:38:37,751 --> 00:38:41,705
And, if you really wanted to make
that kind of a first class experience.

681
00:38:41,735 --> 00:38:46,945
But in general, I think that, Linear just
screams kind of database approach to me.

682
00:38:47,275 --> 00:38:51,061
although I do, I know they are, I
believe using Yjs, for some of the issue.

683
00:38:51,423 --> 00:38:55,473
text now could be wrong, but I
think they do use it or a CRDT.

684
00:38:55,706 --> 00:38:58,116
it might be a different CRDT, but
I think they're using some sort

685
00:38:58,116 --> 00:38:59,906
of collaborative text editor.

686
00:39:00,557 --> 00:39:05,827
so given that you've seen quite a couple
of different customers and products

687
00:39:05,847 --> 00:39:11,597
build their own sync engines, any sort of
interesting, almost second order effects

688
00:39:11,637 --> 00:39:17,967
that you've seen there, unexpected things,
new challenges that you didn't see in,

689
00:39:18,257 --> 00:39:21,167
in previous applications, things like.

690
00:39:21,392 --> 00:39:25,232
Database migrations or other
things, which sort of challenges

691
00:39:25,922 --> 00:39:27,102
and problems have you seen?

692
00:39:27,716 --> 00:39:32,606
Yeah, I think whenever you're dealing
with data on S3, data migrations do

693
00:39:32,606 --> 00:39:35,876
become really interesting because
you're not just sort of writing a

694
00:39:36,026 --> 00:39:38,526
database query and issuing an update.

695
00:39:39,556 --> 00:39:43,156
Usually some form of
gradual lazy migration.

696
00:39:43,156 --> 00:39:46,686
So it's kind of like the application
that's reading the data has to know

697
00:39:46,686 --> 00:39:50,166
how to transition from version one
to two and two to three and then

698
00:39:50,736 --> 00:39:52,176
kind of apply those consecutively.

699
00:39:52,466 --> 00:39:57,286
And so that logic tends to linger
around in the application for as long

700
00:39:57,286 --> 00:39:59,346
as you have old documents to support.

701
00:39:59,719 --> 00:40:04,599
and I think there's ways to do schema
migrations or schema changes that

702
00:40:04,599 --> 00:40:06,049
don't require a migration as well.

703
00:40:06,049 --> 00:40:09,981
Like, I think that the, It was
at Google and we, you know, there

704
00:40:09,981 --> 00:40:12,331
were certain rules about what you
could do with protocol buffers.

705
00:40:12,734 --> 00:40:16,144
that would ensure that they were
always backward and forward compatible.

706
00:40:16,291 --> 00:40:20,811
and so I think, you know, things like a
required field always has to be required.

707
00:40:20,811 --> 00:40:21,111
And so.

708
00:40:21,854 --> 00:40:25,511
Deciding being delicate of
when you call a field required.

709
00:40:25,957 --> 00:40:28,707
there's certain kind of things you can
do at the schema design level and schema

710
00:40:28,707 --> 00:40:34,561
migration or schema change migration
level that you can avoid kind of having

711
00:40:34,561 --> 00:40:36,031
to implement any sort of migration.

712
00:40:36,041 --> 00:40:39,211
It can kind of be more
access time oriented.

713
00:40:39,691 --> 00:40:43,281
So I think doing that
has been where I've seen.

714
00:40:43,831 --> 00:40:46,751
It will be successful with that,
in terms of second order effects, I

715
00:40:46,751 --> 00:40:50,541
think kind of goes back to like, once
you have the sync server, people are

716
00:40:50,541 --> 00:40:54,211
like, oh, this is now a place where
I can trigger this notification or I

717
00:40:54,211 --> 00:40:59,837
can do this check or I can, you know,
so I think we've sort of seen these,

718
00:41:00,257 --> 00:41:02,077
these backends kind of grow in scope.

719
00:41:02,244 --> 00:41:04,974
you know, we want that to be first
class part of the application that

720
00:41:04,974 --> 00:41:06,504
can do whatever you want it to do.

721
00:41:07,046 --> 00:41:08,076
That makes a lot of sense.

722
00:41:08,116 --> 00:41:14,023
And yeah, I think this is, an area that,
has already caused a lot of, headaches,

723
00:41:14,073 --> 00:41:18,393
schema migrations, data migrations in
general, but now that we are rethinking

724
00:41:18,403 --> 00:41:24,833
the data architectures at large here,
we also need to rethink that part and

725
00:41:24,843 --> 00:41:29,313
like you've mentioned, when you have all
the data in a single Postgres database,

726
00:41:29,323 --> 00:41:33,961
then you can at least like apply like
your old playbooks there, but now if all

727
00:41:33,961 --> 00:41:39,748
of your data is in an S3 bucket, laid
out in whatever way, now you do need a

728
00:41:39,748 --> 00:41:41,878
different new approach to deal with that.

729
00:41:41,968 --> 00:41:46,441
And, That is one way to deal
with it, to bake in the migration

730
00:41:46,441 --> 00:41:48,201
logic into your app logic.

731
00:41:48,701 --> 00:41:52,831
But, that is also, I think that
also comes with its own downsides.

732
00:41:52,831 --> 00:41:58,081
This way you're like litter some of
that code that was once very clear.

733
00:41:58,341 --> 00:42:02,041
and now you make it less clear
because you need to account for.

734
00:42:02,331 --> 00:42:07,101
That historical evolution, a project
that I want to shout out here is the

735
00:42:07,111 --> 00:42:12,848
project, Cambria by the folks at In I've
actually studied this project myself quite

736
00:42:12,848 --> 00:42:17,718
intensively and I've rebuilt it, myself
a few times once even on a type level

737
00:42:17,738 --> 00:42:20,425
just to, provide a nice type save API.

738
00:42:21,480 --> 00:42:25,570
Given that the original implementation
rather lets you specify those

739
00:42:25,570 --> 00:42:27,760
sort of projection rules in YAML.

740
00:42:28,160 --> 00:42:31,630
But, I've heard some rumors that
they're thinking of like rebooting

741
00:42:31,660 --> 00:42:32,970
that project at some point.

742
00:42:32,970 --> 00:42:34,370
So fingers crossed for that.

743
00:42:34,970 --> 00:42:39,250
And yeah, another approach that
I'm investigating heavily myself,

744
00:42:39,290 --> 00:42:42,050
given I have my fair share of like.

745
00:42:42,185 --> 00:42:48,081
Database migration traumas, that I
tried to remedy with, starting Prisma,

746
00:42:48,661 --> 00:42:52,065
but now I'm, trying a different
approach with event sourcing.

747
00:42:52,525 --> 00:42:57,960
Where if you basically split
up your documents your database

748
00:42:58,280 --> 00:43:02,900
into a dedicated write model and
derive the read model from it.

749
00:43:02,930 --> 00:43:07,336
The core insight here is basically
that if you split this up into two

750
00:43:07,336 --> 00:43:11,566
parts, the schema for your read
model, that is typically the thing.

751
00:43:11,936 --> 00:43:16,916
That changes orders of magnitudes more
often where you have different kind of

752
00:43:16,917 --> 00:43:21,276
queries that you want to do different
sort of aggregations and where you want

753
00:43:21,276 --> 00:43:25,376
to maybe change the database layout to
make certain queries faster and more

754
00:43:25,376 --> 00:43:29,236
efficient and then the write operations.

755
00:43:29,551 --> 00:43:34,641
Those are much more bound to the
domain of when stuff actually happens.

756
00:43:34,941 --> 00:43:37,781
So, and that's changes way less over time.

757
00:43:37,781 --> 00:43:42,350
Like, maybe you want to capture,
someone's preference on email,

758
00:43:42,351 --> 00:43:47,441
marketing emails on, on signup, but
historically you can way easier say,

759
00:43:47,441 --> 00:43:49,431
like, actually we default to no.

760
00:43:49,905 --> 00:43:52,135
but a user signup event.

761
00:43:52,345 --> 00:43:55,785
Is always valid and way easier to upgrade.

762
00:43:56,175 --> 00:44:00,835
And then you can basically reapply
all prior events into the new read

763
00:44:00,835 --> 00:44:03,665
model that you can change very easily.

764
00:44:03,665 --> 00:44:06,495
And you can even have like
multiple read models all at once.

765
00:44:06,915 --> 00:44:11,581
So, that is what I'm exploring right
now on the umbrella of Livestore.

766
00:44:12,061 --> 00:44:16,268
But, that also comes then
requires that rigor to split it

767
00:44:16,308 --> 00:44:17,938
up into a read and write model.

768
00:44:18,398 --> 00:44:20,208
But yeah, curious whether
you have thoughts on that.

769
00:44:20,756 --> 00:44:21,866
Yeah, that's really interesting.

770
00:44:21,866 --> 00:44:27,166
I think that event sourcing in general
does sort of simplify migrations.

771
00:44:27,176 --> 00:44:30,706
If you're willing to kind of go back
over the event source log and regenerate,

772
00:44:30,726 --> 00:44:35,096
because then as long as you represented
all of the data that matters, then you

773
00:44:35,106 --> 00:44:37,961
can essentially just add fields as.

774
00:44:38,151 --> 00:44:38,891
As needed to

775
00:44:39,408 --> 00:44:44,708
another problem that emerges in that
world is like, if your domain produces

776
00:44:44,728 --> 00:44:50,448
a lot of events, so let's say you
build a TL draw and whenever you move

777
00:44:50,448 --> 00:44:55,391
a rectangle, that creates, you could
model it in a way that when you let go

778
00:44:55,391 --> 00:44:58,861
of the rectangle that creates an event,
but you could even model it in a way.

779
00:44:59,161 --> 00:45:03,995
Where, like whenever the browser
registered a new move event, dragging

780
00:45:03,995 --> 00:45:10,435
it can cause 5, 000 events and that can
lead to a very long history of events.

781
00:45:10,445 --> 00:45:13,415
So now you gotta keep
that in mind as well.

782
00:45:13,965 --> 00:45:18,501
And, whereas in the traditional mixed
read and write model approach, you

783
00:45:18,501 --> 00:45:23,878
would basically just overwrite the
position and it would not necessarily

784
00:45:24,068 --> 00:45:25,828
cause the database to explode.

785
00:45:26,071 --> 00:45:27,581
because you have too much data.

786
00:45:27,945 --> 00:45:30,898
but yeah, it's all about trade
offs that that is like, what

787
00:45:30,898 --> 00:45:32,428
data management is all about.

788
00:45:32,786 --> 00:45:37,626
maybe a slightly different aspect about
data that, you've also written about,

789
00:45:37,916 --> 00:45:41,056
which is in regards to encrypting data.

790
00:45:41,526 --> 00:45:44,863
So, you've written a great
blog post about that.

791
00:45:45,183 --> 00:45:48,666
can you tell us more about that
blog post and, what it's about?

792
00:45:49,040 --> 00:45:52,280
Yeah, so this came out of
when we were with Y-Sweet.

793
00:45:52,300 --> 00:45:56,595
We wanted to do We wanted to have
store the data locally in the

794
00:45:56,595 --> 00:45:58,215
client, at least as an option.

795
00:45:58,711 --> 00:46:01,351
so we looked at the options that
were available or, you know, local

796
00:46:01,351 --> 00:46:06,625
storage, indexed db, opfs, origin,
private file system, realized that

797
00:46:06,655 --> 00:46:10,255
indexed db was really the kind of the
right way to go for this right now.

798
00:46:10,375 --> 00:46:14,255
have high hopes on opfs, but
they're still, I mean, they

799
00:46:14,255 --> 00:46:16,335
all kind of have flaws, but.

800
00:46:16,715 --> 00:46:20,315
Index DB is like the best people
know the flaws the best, I guess,

801
00:46:20,425 --> 00:46:21,685
and how to work around them.

802
00:46:21,695 --> 00:46:23,148
So, looked at index DB.

803
00:46:23,148 --> 00:46:27,488
But the problem that we found with
all of them is that all of them store

804
00:46:27,488 --> 00:46:32,568
the data in plain text, and that's
not just a theoretical problem.

805
00:46:32,568 --> 00:46:34,438
There is at least a couple months ago.

806
00:46:34,438 --> 00:46:39,868
Now, there was some, you know, NPM
and pie pie modules out there that

807
00:46:39,868 --> 00:46:43,558
would read some application data
from these plain text sources.

808
00:46:43,991 --> 00:46:45,911
it's kind of a real problem
that people have identified.

809
00:46:46,856 --> 00:46:47,946
And has been exploited.

810
00:46:48,370 --> 00:46:51,370
so we wanted to make sure that we
provided an option that at least as,

811
00:46:51,410 --> 00:46:54,160
as best as possible would prevent that.

812
00:46:54,666 --> 00:46:57,023
so we said, okay, well,
browsers have web crypto.

813
00:46:57,033 --> 00:46:58,323
We can encrypt all this.

814
00:46:58,663 --> 00:47:01,163
but then there's this problem
of where do you store the key?

815
00:47:01,250 --> 00:47:04,090
because you could start on on the
server, but then kind of defeats

816
00:47:04,090 --> 00:47:07,446
the purpose if you're offline,
of then accessing that data.

817
00:47:07,916 --> 00:47:09,746
So realize that.

818
00:47:10,260 --> 00:47:16,333
don't really have a good way to
store a key kind of credential.

819
00:47:16,703 --> 00:47:21,753
we've got like WebAuthn, but WebAuthn is
a bit more secure, like, which is where

820
00:47:21,753 --> 00:47:23,253
you have pass keys and things like that.

821
00:47:23,513 --> 00:47:24,863
It's a bit more opinionated.

822
00:47:24,873 --> 00:47:29,590
It uses the operating systems key chain,
but it, doesn't really expose that to

823
00:47:29,590 --> 00:47:33,690
you as any sort of low level API that
you can store your own secrets in.

824
00:47:34,181 --> 00:47:37,861
What has started happening is that
some browsers, particularly Chromium

825
00:47:37,901 --> 00:47:44,025
based browsers, Google Chrome, Edge,
Rave, have built in something called

826
00:47:44,025 --> 00:47:48,805
App-Bound encryption, and they're just
using this for cookies, but the idea

827
00:47:48,805 --> 00:47:54,295
is that the browser will store, cookies
in, you know, on disk as they always

828
00:47:54,305 --> 00:47:59,785
have, but they'll be encrypted on disk,
and then the symmetric key to that will

829
00:47:59,785 --> 00:48:05,463
be stored in the, Operating systems
keychain and the operating system is set

830
00:48:05,463 --> 00:48:09,453
up to at least in theory, and there's
been some vulnerabilities here, too.

831
00:48:09,453 --> 00:48:14,036
But, at least in theory, only
give that private key back to

832
00:48:14,036 --> 00:48:18,365
the browser process itself not to
another process that attempts to

833
00:48:18,585 --> 00:48:20,180
impersonate, the browser process.

834
00:48:20,710 --> 00:48:24,436
So what we landed on, which was pretty
surprising to me, that this was kind

835
00:48:24,436 --> 00:48:26,976
of the best available path right now.

836
00:48:27,566 --> 00:48:33,056
But if you enable local storage, we
encrypt it stored in index DB and

837
00:48:33,056 --> 00:48:35,166
then store the key in a cookie and.

838
00:48:35,796 --> 00:48:39,776
Kind of piggyback on that being
App-Bound encrypted in at least

839
00:48:39,776 --> 00:48:40,736
in browsers to support it.

840
00:48:41,200 --> 00:48:42,470
That is very interesting.

841
00:48:42,470 --> 00:48:46,770
Yeah, I've been studying, cryptography,
particularly in a browser context,

842
00:48:46,780 --> 00:48:49,510
also a bit more for various reasons.

843
00:48:49,550 --> 00:48:55,380
I am, trying to see what would
it take to, do the entire, sync.

844
00:48:55,617 --> 00:49:00,951
messages for Livestore, what would it
be, for them to be enter and encrypted,

845
00:49:01,301 --> 00:49:06,591
but the hard part is not the encryption,
but the hard part is the end to end

846
00:49:07,011 --> 00:49:11,505
where, the various ends own their keys.

847
00:49:11,505 --> 00:49:14,910
And there's a, we should do an
entire episode just about that.

848
00:49:14,943 --> 00:49:18,619
what's difficult about it, but,
it can all be distilled down to

849
00:49:18,619 --> 00:49:23,096
the hard part about, anything
cryptography related as key management.

850
00:49:23,449 --> 00:49:27,769
And you can either around the side of like
being a little bit more loose with like

851
00:49:27,769 --> 00:49:32,616
how you manage keys, but that defies a lot
of the, purposes and the benefits here.

852
00:49:32,889 --> 00:49:38,269
but then also the, browser makes that
really, really tricky because it has very

853
00:49:38,269 --> 00:49:43,846
constrained APIs and historically it's
always been rather a web document viewer

854
00:49:43,906 --> 00:49:49,514
than a fully fledged application platform
and, we're getting the building blocks.

855
00:49:49,514 --> 00:49:52,327
I mean, you can, use the, web crypto API.

856
00:49:52,611 --> 00:49:57,891
I'm also using the Libsodium projects,
compiled to WASM, which is very

857
00:49:57,891 --> 00:50:00,041
powerful and gives you a couple.

858
00:50:00,518 --> 00:50:05,468
of advanced, algorithms, et cetera,
that you can use for, symmetric or

859
00:50:05,468 --> 00:50:08,348
asymmetric encryption, signing, et cetera.

860
00:50:08,751 --> 00:50:13,148
and pass keys, I think are also
like, a super important foundation.

861
00:50:13,663 --> 00:50:16,288
But, they also get you just so far.

862
00:50:16,288 --> 00:50:20,248
And I think they don't really help
you for the encryption as such,

863
00:50:20,258 --> 00:50:23,018
but rather for signing messages.

864
00:50:23,028 --> 00:50:25,518
So I think we're still
lacking a few building blocks.

865
00:50:25,788 --> 00:50:30,775
So very excited to hear about this
what, what it was again, App-Bound.

866
00:50:31,275 --> 00:50:37,785
App-Bound encryption, so ideally at some
point, this goes even beyond cookies that,

867
00:50:37,838 --> 00:50:41,378
this can be applied for other storage
mechanisms, but I like the approach

868
00:50:41,668 --> 00:50:46,101
to, basically encrypt it and then you
reduce it to the key management problem

869
00:50:46,401 --> 00:50:52,181
and that you put into a cookie, which
also, there's another question, which is

870
00:50:52,211 --> 00:50:54,631
what happens if that cookie goes away?

871
00:50:55,048 --> 00:50:57,378
did you figure out a, an answer for that?

872
00:50:58,065 --> 00:50:58,745
we don't.

873
00:50:58,775 --> 00:51:02,945
We just set it to a long expiration,
but it's the thinking there was like,

874
00:51:02,945 --> 00:51:08,448
if the user is clearing their cookies
on that tab or on that hosting, they

875
00:51:08,448 --> 00:51:10,718
probably want to destroy the data.

876
00:51:10,778 --> 00:51:13,128
And so are they, you know,
they want to be logged out.

877
00:51:13,400 --> 00:51:17,013
so we actually saw it as the
right thing to do to, bind it.

878
00:51:17,343 --> 00:51:21,143
The other nice thing about that is
like, unlike indexed DB cookies can

879
00:51:21,143 --> 00:51:22,413
actually have an expiration date.

880
00:51:22,413 --> 00:51:24,933
So we could set an expiration of a week.

881
00:51:25,133 --> 00:51:28,343
we're still relying on the browser to
enforce that, but if the browser enforces

882
00:51:28,353 --> 00:51:33,083
that, and then, you know, two weeks later,
that person is fully hacked, including

883
00:51:33,083 --> 00:51:36,613
their operating system key chain, the
browser, at least in theory, will have

884
00:51:36,803 --> 00:51:40,483
deleted that private key and then the
data that's in IndexedDB will be gone.

885
00:51:40,803 --> 00:51:43,533
So that's actually, funny
enough, additional functionality.

886
00:51:43,533 --> 00:51:45,703
It was just incidental to the,
to using cookies for that.

887
00:51:46,163 --> 00:51:46,623
Right.

888
00:51:46,686 --> 00:51:49,436
I like this trick a lot
and I got to look into it.

889
00:51:49,756 --> 00:51:54,370
One thing to point out still is, you've
mentioned that this mechanism is only

890
00:51:54,370 --> 00:52:00,563
available in Chromium browsers anyway,
but, cookies and IndexedDB, OPFS, et

891
00:52:00,563 --> 00:52:05,270
cetera, all of that is available in
other browsers and namely Safari as well.

892
00:52:05,490 --> 00:52:11,483
One thing that, people find out the hard
way about Safari is that it automatically

893
00:52:11,503 --> 00:52:16,363
deletes a user's data after seven days
if they haven't visited that website.

894
00:52:16,913 --> 00:52:21,673
So if you're building a fully
local-first web experience where

895
00:52:21,673 --> 00:52:26,686
someone, creates some precious data,
in Safari and maybe doesn't sync it

896
00:52:26,686 --> 00:52:31,906
yet to somewhere else, go on vacation,
come back and poof, the data is gone.

897
00:52:32,196 --> 00:52:36,676
So I think as app builders, we
need to be aware of that and

898
00:52:36,686 --> 00:52:38,476
detect, Hey, is this Safari?

899
00:52:38,886 --> 00:52:42,577
And in Safari, make this part of the
product experience show sort of like

900
00:52:42,713 --> 00:52:44,926
a message, like, Hey, be careful.

901
00:52:44,966 --> 00:52:46,226
Your data might go away.

902
00:52:46,586 --> 00:52:48,436
There are ways to remedy that.

903
00:52:48,506 --> 00:52:53,510
And, to, for example, if you make
the Safari app, a, progressive web

904
00:52:53,510 --> 00:52:56,170
app by adding it to the home screen.

905
00:52:56,330 --> 00:52:57,910
That limitation goes away.

906
00:52:58,214 --> 00:53:03,903
but app builders need to be aware that
they can make the app users aware.

907
00:53:04,156 --> 00:53:08,370
it's just something that, I
think is important to, note.

908
00:53:08,880 --> 00:53:11,590
Yeah, I think that's an example
of a number of cases where the

909
00:53:11,590 --> 00:53:15,480
browsers are just not optimized for
local-first apps, unfortunately.

910
00:53:15,676 --> 00:53:21,416
you know, the, I think the ability to just
store low level access to the operating

911
00:53:21,416 --> 00:53:23,436
systems key chain is another, where.

912
00:53:23,906 --> 00:53:28,416
Browsers have improved a ton in terms
of what they expose of the APIs, but I

913
00:53:28,416 --> 00:53:31,876
think they're still lagging when it comes
to that storage and encrypted storage.

914
00:53:32,426 --> 00:53:33,466
Yeah, totally.

915
00:53:34,006 --> 00:53:38,793
So, maybe slightly, moving to
another browser related topic.

916
00:53:39,010 --> 00:53:43,910
you've been both through your
work, Through your prior role, and

917
00:53:43,920 --> 00:53:47,270
also as part of Jamsocket, you've
been dealing with quite a bit

918
00:53:47,270 --> 00:53:51,130
of WebAssembly, any interesting
story to share about WebAssembly?

919
00:53:51,733 --> 00:53:53,103
guess I really wanted.

920
00:53:53,768 --> 00:53:55,518
I wanted to build the
company around WebAssembly.

921
00:53:55,518 --> 00:53:59,568
I wanted WebAssembly to take off,
particularly like server side,

922
00:53:59,568 --> 00:54:03,698
client side, that kind of having
isomorphic client side server

923
00:54:03,698 --> 00:54:05,628
side code would be a big thing.

924
00:54:05,858 --> 00:54:10,188
And I've, I guess, just generally
soured on WebAssembly a little bit.

925
00:54:10,330 --> 00:54:14,540
I think that it where I've seen
it work really well is when it's

926
00:54:14,750 --> 00:54:17,760
in the application layer and
you kind of have an application.

927
00:54:18,160 --> 00:54:21,810
there's a couple examples I like to go to
that are like effectively the same model.

928
00:54:21,893 --> 00:54:24,186
the same kind of architecture, Figma.

929
00:54:24,186 --> 00:54:27,976
There's a company called Modify a few
others that I'm, I'm blanking on, but the

930
00:54:28,066 --> 00:54:36,783
architecture is essentially a JavaScript
UI, with a, webAssembly, WebGL, WebGPU

931
00:54:36,823 --> 00:54:41,386
kind of rendered canvas, behind it, so
like Figma, you know, the core engine

932
00:54:41,386 --> 00:54:46,030
is, I believe, in C, talking to WebGL,
with Modify, it's in Rust and WebGPU,

933
00:54:47,586 --> 00:54:52,536
but it's literally like, The application
is layered that way that on screen,

934
00:54:52,586 --> 00:54:55,125
there is the canvas behind the UI.

935
00:54:55,125 --> 00:54:57,833
They're written in two different languages
and they just talk to each other.

936
00:54:58,170 --> 00:55:01,883
so I think that is the most promising
architecture that I see for WebAssembly,

937
00:55:02,426 --> 00:55:05,306
where I think it's been harder.

938
00:55:05,531 --> 00:55:09,981
To get right is building something like
a library that is ultimately consumed

939
00:55:09,991 --> 00:55:15,071
by JavaScript developers, but written in
WebAssembly, I think there's just so much

940
00:55:15,071 --> 00:55:19,641
friction still in the bundling that, I've
kind of soured on that as an approach.

941
00:55:19,915 --> 00:55:20,295
Right.

942
00:55:20,455 --> 00:55:25,335
I mean, I agree in that regard that I
wish there was already, we'd be further

943
00:55:25,345 --> 00:55:30,615
along with WebAssembly, but I think
it's a bit of a chicken egg problem that

944
00:55:30,615 --> 00:55:33,135
we need more inspiring applications.

945
00:55:33,475 --> 00:55:36,705
That makes people feel
like, wow, that is possible.

946
00:55:36,818 --> 00:55:38,838
I didn't recognize that this was the web.

947
00:55:39,162 --> 00:55:40,391
it feels so fast.

948
00:55:40,391 --> 00:55:45,031
And I think that is still true
and, more true than, than ever

949
00:55:45,051 --> 00:55:46,688
that WebAssembly, I think.

950
00:55:46,803 --> 00:55:48,993
Can unlock whole new experiences.

951
00:55:49,013 --> 00:55:53,293
And there is a few Lighthouse examples
like Figma that stand out here.

952
00:55:53,303 --> 00:55:58,546
Also a big shout out, to the
folks building Makepad, which is

953
00:55:58,596 --> 00:56:03,416
a super ambitious project, which
is, basically the same way as like.

954
00:56:03,710 --> 00:56:07,530
I'm probably going to do it, I don't
do it justice by pitching it, but,

955
00:56:07,886 --> 00:56:12,536
I just want to speak to the ambition
where it's basically like Unreal Engine

956
00:56:12,546 --> 00:56:14,586
is sort of like it's full engine.

957
00:56:14,596 --> 00:56:20,260
They, they're building their own platform
and including, like a, a rendering layer

958
00:56:20,520 --> 00:56:26,430
and, sort of like as a few people think
about, think that MakePad is an editor.

959
00:56:26,700 --> 00:56:29,750
No, MakePad has just as an example app.

960
00:56:30,090 --> 00:56:34,510
Build an editor in which they build
make pad, which is just so phenomenal.

961
00:56:34,790 --> 00:56:38,993
So, and make pad is just
such an incredibly fast app.

962
00:56:38,993 --> 00:56:41,373
So you should definitely
check it out, go to make pad.

963
00:56:41,553 --> 00:56:47,356
dev and then press the option key, to see
like how the entire code editor expands.

964
00:56:47,356 --> 00:56:51,296
So apps like that get me very
excited about what's possible with

965
00:56:51,296 --> 00:56:54,896
WASM, but, they're fully, they're
building everything in Rust.

966
00:56:54,896 --> 00:56:57,430
They're fully leaning
into everything, there.

967
00:56:57,480 --> 00:57:02,043
And I think the either or, where you want
to like, combined one step at a time.

968
00:57:02,053 --> 00:57:07,013
I think that's a. Tooling problem,
partially it's also a trade off

969
00:57:07,033 --> 00:57:12,173
problem where if you move a lot of
data back and forth between WASM and

970
00:57:12,173 --> 00:57:14,383
JavaScript, that doesn't come for free.

971
00:57:14,783 --> 00:57:17,566
So I think, you got to keep that in mind.

972
00:57:17,846 --> 00:57:22,226
I've seen a few, I think the, the
RepliCache folks actually in the past have

973
00:57:22,226 --> 00:57:26,796
written a lot of their stuff in Rust and
then moved to JavaScript because of that

974
00:57:27,136 --> 00:57:29,573
boundary crossing being, too expensive.

975
00:57:30,248 --> 00:57:35,851
But, I think not every use case suffers
from that problem, but, I want to turn

976
00:57:35,851 --> 00:57:42,558
it around and, invite anyone who is
excited about WebAssembly as, seeing

977
00:57:42,558 --> 00:57:46,858
that as an opportunity to make things
significantly better, like working

978
00:57:46,858 --> 00:57:52,058
on projects like WasmBindGen or other
things, I think the Deno folks are

979
00:57:52,078 --> 00:57:56,766
pushing heavily on that, so I'm seeing
this glass half full and I think the

980
00:57:56,776 --> 00:57:58,326
glass is going to get full pretty soon.

981
00:57:58,856 --> 00:58:03,601
Yeah, I think to your point about like,
the JavaScript WebAssembly boundary

982
00:58:03,601 --> 00:58:07,871
crossing, and I think that it comes down
to just placing that boundary in the right

983
00:58:07,871 --> 00:58:12,898
place when it comes to, applications like
the Figma model of sort of JavaScript

984
00:58:12,908 --> 00:58:17,915
front end with, renderer in WebAssembly,
make pad is is a great example.

985
00:58:17,915 --> 00:58:20,765
I think of going like all
the way in on WebAssembly.

986
00:58:21,125 --> 00:58:22,605
Another one's called Remix.

987
00:58:22,682 --> 00:58:26,052
and I think what's notable about
both cases is that to do that

988
00:58:26,052 --> 00:58:30,482
well, they've had to basically be
living in the GUI toolkit layer.

989
00:58:30,482 --> 00:58:33,172
Like, they've been writing
their own code or adapting a

990
00:58:33,172 --> 00:58:34,242
lot of their own code for it.

991
00:58:34,252 --> 00:58:36,487
So I think that's, Not
for the faint of heart.

992
00:58:36,537 --> 00:58:41,183
I think that people who have done it have
built amazing software, but what comes

993
00:58:41,183 --> 00:58:45,253
up more often when I talk to people is
like they there's a scarcity of rust

994
00:58:45,263 --> 00:58:50,533
developers and they want to optimize the
rust developers to working on kind of the

995
00:58:50,533 --> 00:58:56,123
engine component and then be able to hire
React developers and Svelte developers and

996
00:58:56,453 --> 00:59:03,108
kind of front end web developers to work
on the GUI where it may not be Like, you

997
00:59:03,108 --> 00:59:04,958
know, think about Figma's UI components.

998
00:59:04,958 --> 00:59:07,953
Like they're not super performance
sensitive in the way that the canvas is.

999
00:59:08,379 --> 00:59:09,159
Yeah, totally.

1000
00:59:09,189 --> 00:59:14,296
I think it just takes, some bold thinkers
and this is not something where you're

1001
00:59:14,296 --> 00:59:18,846
gonna rebuild the world in two weeks,
this is really something you gotta,

1002
00:59:19,183 --> 00:59:22,213
put in the five, 10 years possibly.

1003
00:59:22,544 --> 00:59:28,168
to really build something phenomenal,
but I think the, rewards are massive and,

1004
00:59:28,231 --> 00:59:32,991
I'm really looking forward to getting
kind of alternatives to something like

1005
00:59:33,021 --> 00:59:37,671
React that provide different trade offs
and that allow you to build like really,

1006
00:59:37,671 --> 00:59:41,941
really high performance applications
and fundamentally React biases towards

1007
00:59:41,951 --> 00:59:47,836
simplicity and biases towards that
you can, Prevent, not so experienced

1008
00:59:47,876 --> 00:59:52,756
engineers to, hurt themselves or
others and drag the application down.

1009
00:59:53,096 --> 00:59:57,096
But I think there's a different, trade
off space as well, where you bias more

1010
00:59:57,096 --> 01:00:00,656
towards performance and you need to know
a little bit more what you're doing.

1011
01:00:01,381 --> 01:00:06,951
And particularly now with AI being on
the horizon, I think we can rethink

1012
01:00:06,971 --> 01:00:11,381
a lot of trade offs significantly
where engineering team sizes, maybe,

1013
01:00:11,624 --> 01:00:15,778
get reduced as well, but that's
the topic for another conversation.

1014
01:00:16,093 --> 01:00:21,693
But, related though, in regards to AI,
you've recently also launched a new

1015
01:00:21,703 --> 01:00:25,026
project, that is certainly adjacent to AI.

1016
01:00:25,026 --> 01:00:26,356
It's called ForeverVM.

1017
01:00:26,736 --> 01:00:29,576
can you share a little bit
more what that is about?

1018
01:00:29,793 --> 01:00:30,072
Yeah.

1019
01:00:30,072 --> 01:00:32,802
So pretty much from the beginning with
Jamsocket, one of the ways we've seen

1020
01:00:32,802 --> 01:00:37,782
people use it because we run these
sandbox processes on demand is people

1021
01:00:37,782 --> 01:00:39,852
have run LLM generated code in them.

1022
01:00:39,916 --> 01:00:40,166
actually.

1023
01:00:40,691 --> 01:00:42,621
Going back to the beginning,
it wasn't even LLM generated.

1024
01:00:42,691 --> 01:00:44,471
This was sort of pre chat GPT.

1025
01:00:44,837 --> 01:00:47,757
it was things like Jupyter
notebooks, but over time we see

1026
01:00:47,757 --> 01:00:49,647
more and more LLM generated code.

1027
01:00:50,037 --> 01:00:51,427
and it's, you know, it's good.

1028
01:00:51,447 --> 01:00:54,247
I think we're, we're like competitive
with other products for that, but we

1029
01:00:54,407 --> 01:00:58,497
kind of realized, first of all, we're not
really positioning the product that way.

1030
01:00:58,731 --> 01:00:59,351
but also.

1031
01:00:59,776 --> 01:01:02,726
We're not building the product
necessarily to be like the best

1032
01:01:02,736 --> 01:01:04,286
for that from first principles.

1033
01:01:04,296 --> 01:01:08,436
Like if we were just say, like, I want
an LLM to be able to execute code.

1034
01:01:08,706 --> 01:01:10,426
What would that look like
from first principles?

1035
01:01:10,426 --> 01:01:13,696
And we kind of thought, well, we
don't really care about the session.

1036
01:01:13,696 --> 01:01:17,121
We don't really care about, you know,
we want it to From the LLM's point of

1037
01:01:17,121 --> 01:01:19,221
view, feel like it can always run code.

1038
01:01:19,221 --> 01:01:22,981
It doesn't have to start a sandbox and
stop a sandbox when it's done to cut

1039
01:01:22,981 --> 01:01:24,171
down on costs and things like that.

1040
01:01:24,171 --> 01:01:29,241
We, we kind of like cut out the rest of
it, make that into the abstraction and

1041
01:01:29,241 --> 01:01:32,901
build it, frankly, into something that
we can position for those products so

1042
01:01:32,901 --> 01:01:35,941
that we're not confusing people who are
like, I thought you did sync engines.

1043
01:01:36,294 --> 01:01:40,164
now you're telling me running AI code
and it's like, architecturally, they

1044
01:01:40,164 --> 01:01:43,064
can actually be fairly similar, but, we
wanted to build a product around that.

1045
01:01:43,084 --> 01:01:45,582
So We have forever VM, it is.

1046
01:01:46,422 --> 01:01:47,202
Way to think about it.

1047
01:01:47,202 --> 01:01:52,352
It's like an API that runs Python
code in a unbounded session.

1048
01:01:52,469 --> 01:01:56,359
so by that, I mean, if you, kind of
make an API call and get a machine

1049
01:01:56,369 --> 01:02:02,139
ID, maybe ABC 123, you can run
instructions on that machine set a

1050
01:02:02,149 --> 01:02:03,549
equals three or something like that.

1051
01:02:03,974 --> 01:02:07,864
Two years from now, if you kept
that machine around, you can query

1052
01:02:07,864 --> 01:02:12,174
the value of a, you know, a plus
five, and then you get back a value.

1053
01:02:12,257 --> 01:02:16,611
and the way we're doing that behind the
scenes is using, memory snapshotting

1054
01:02:16,661 --> 01:02:18,651
of the underlying Python process.

1055
01:02:19,021 --> 01:02:23,176
So we kind of from the ground
up architected the whole system

1056
01:02:23,176 --> 01:02:24,386
around this and it's kind of neat

1057
01:02:24,932 --> 01:02:25,752
fascinating.

1058
01:02:25,752 --> 01:02:25,992
Yeah.

1059
01:02:26,012 --> 01:02:30,712
My mind is also going to other
technologies like mentioned Temporal

1060
01:02:30,732 --> 01:02:35,632
before, but there's also really
fascinating project called Golem VM,

1061
01:02:35,882 --> 01:02:41,756
which I think is also, Also employing some
really interesting tricks, to use WASM

1062
01:02:41,796 --> 01:02:47,426
and knowledge about, the WASM memory to
make sort of checkpoints where you can

1063
01:02:47,696 --> 01:02:51,426
restore and resume computation or retry.

1064
01:02:51,846 --> 01:02:56,707
And yeah, I love that, Yeah, we,
we get some bolder ideas out there.

1065
01:02:56,997 --> 01:03:02,354
and particularly now when there is
the cost of writing code has come

1066
01:03:02,354 --> 01:03:07,447
down so much and, now it's also
people write that code who know even

1067
01:03:07,447 --> 01:03:09,207
less about whether it's good or not.

1068
01:03:09,527 --> 01:03:14,842
So we need to put it into boxes
that are somewhat blast safe.

1069
01:03:15,086 --> 01:03:18,996
but also long, like durable in a
way that doesn't break the bank.

1070
01:03:19,406 --> 01:03:24,456
And I love how that is like an entirely
different product, but yet leverages all

1071
01:03:24,456 --> 01:03:28,969
the benefits and all the, foundations
that he's built with Jamsocket, or with,

1072
01:03:29,029 --> 01:03:30,892
I guess with Plain for that matter.

1073
01:03:31,182 --> 01:03:32,332
That is very, very cool.

1074
01:03:33,287 --> 01:03:34,057
Yeah, thanks.

1075
01:03:34,074 --> 01:03:38,984
one of the things that's been really
cool to see is that if we give an LLM

1076
01:03:39,254 --> 01:03:42,964
the ability to write this code and get
responses back very quickly, like kind

1077
01:03:42,964 --> 01:03:48,847
of just treat it as a local-repl, that
the AIs can kind of do more like they get

1078
01:03:48,847 --> 01:03:52,837
that fast feedback loop and they can make
mistakes and correct them almost faster

1079
01:03:52,837 --> 01:03:56,677
than, and in some cases we've observed
them doing this faster than a reasoning

1080
01:03:56,677 --> 01:03:59,367
model could kind of just generate
the right code in the first place.

1081
01:03:59,377 --> 01:04:00,167
So that's been pretty neat.

1082
01:04:00,847 --> 01:04:01,377
Nice.

1083
01:04:02,167 --> 01:04:06,117
Any other things that you would
like to share with the audience?

1084
01:04:06,387 --> 01:04:11,030
if you want to find me online, I'm,
paulgb on Twitter or X and paulbutler.

1085
01:04:11,030 --> 01:04:12,730
org on BlueSky.

1086
01:04:13,307 --> 01:04:13,727
jamsocket.

1087
01:04:13,747 --> 01:04:16,227
com is the site, jamsockethq on Twitter.

1088
01:04:16,627 --> 01:04:18,337
also on BlueSky is jamsocket.

1089
01:04:18,337 --> 01:04:18,727
com.

1090
01:04:19,180 --> 01:04:20,160
and, yeah, forevervm.

1091
01:04:20,430 --> 01:04:22,140
com is the product we
were just talking about.

1092
01:04:22,690 --> 01:04:23,130
Perfect.

1093
01:04:23,130 --> 01:04:26,660
We're going to put links to all
of those things in the show notes.

1094
01:04:27,100 --> 01:04:29,800
Paul, thank you so much for
coming on the show today.

1095
01:04:29,854 --> 01:04:34,634
I've learned a lot about so many different
topics and yeah, really enjoyed it.

1096
01:04:34,654 --> 01:04:35,064
Thank you.

1097
01:04:35,964 --> 01:04:36,684
Thank you, Johannes.

1098
01:04:36,684 --> 01:04:39,794
And really looking forward to seeing
you at local-first in Berlin this year.

1099
01:04:40,264 --> 01:04:40,664
Perfect.

1100
01:04:40,704 --> 01:04:41,194
See you then.

1101
01:04:41,754 --> 01:04:42,349
See you then.

1102
01:04:42,834 --> 01:04:45,414
Thank you for listening to
the localfirst.fm podcast.

1103
01:04:45,594 --> 01:04:48,684
If you've enjoyed this episode and
haven't done so already, please

1104
01:04:48,684 --> 01:04:49,974
subscribe and leave a review.

1105
01:04:50,364 --> 01:04:52,884
Please also share this episode
with your friends and colleagues.

1106
01:04:53,274 --> 01:04:56,274
Spreading the word about the
podcast is a great way to support

1107
01:04:56,274 --> 01:04:57,984
it and to help me keep it going.

1108
01:04:58,644 --> 01:05:02,064
A special thanks again to Jazz
for supporting this podcast.

1109
01:05:02,364 --> 01:05:03,324
I'll see you next time.