localfirst.fm

A podcast about local-first software development

Listen

Conference

#9 – Dax Raad: Local-First SaaS


The guest of this episode is Dax Raad, who is using local-first in multiple projects including the serverless deployment tool SST.dev, a healthcare app and an upcoming personal finance app. This conversation will explore how local-first simplifies app development, the UX and data patterns he used on and how self-hosting could empower local-first apps.


Mentioned in podcast


Links:

Thank you to Expo and CrabNebula for supporting the podcast.

Transcript

Intro
00:00What do you mean replicate the whole data to the end client?
00:03Like, It's too big.
00:03Like, that can't work.
00:04So I understand the hesitation.
00:06But any like half step in that direction, it just a gateway to
00:10replicating more and more and more.
00:11Cause you just want more and more and more to be instant.
00:13So I had a very traditional mindset around it, which is, okay, we have an
00:17API, the API serves data and we're going to like cache some of that locally.
00:22And I think a lot of people are already doing this stuff, like react-query
00:24put you in that direction where just caching stuff and then refetching.
00:28It kind of gives you some of this like real time local-first feel, but then
00:32you start to hit the limits with that, if you're looking for stuff that's not
00:34literally in the exact view, you're then round tripping with the server again.
00:39The key thing to understand is if you're building an app that people
00:42are actually using every day, the initial load time is really not
00:46something you need to care about.
00:48Welcome to the Local First FM podcast.
00:50I'm your host, Johannes Schickling, and I'm a web developer, a
00:53startup founder, and love the craft of software engineering.
00:57For the past few years, I've been on a journey to build a modern, high quality
01:01music app using web technologies.
01:03And in doing so, I've been falling down the rabbit hole of local first software.
01:07This podcast is your invitation to join me on that journey.
01:11In this episode, I'm speaking to Dax Rad, who is using local first
01:15in multiple projects, including the serverless deployment tool, sst.
01:19dev, a healthcare app, and an upcoming personal finance app.
01:23In this conversation, we explore how local first simplifies app development, the UX
01:29and data patterns he's using, and how self hosting could empower local first apps.
01:34Before getting started, also a big thank you to Expo and Crab
01:38Nebula for supporting this podcast.
01:40And now my interview with Dax.
01:42Hey Dax, welcome to the show.
01:44How are you doing?
01:45Good.
01:45How are you doing?
01:47I'm doing great.
01:48Super excited to have you on the show.
01:50You're certainly also one of the more, well known voices on Twitter
01:54sharing the local-first gospel.
01:56So, seems like you're not just working on one project with local-first,
02:00but almost quite a portfolio of local-first inspired projects.
02:04So super curious to hear more about those, but maybe you want to
02:08share a bit of your story of like, what has led you to local-first?
Local-first motivation and projects overview
02:12yeah, so my name is Dax.
02:13My primary project that I work on is a project called SST.
02:18Uh, we're a, we're a dev tool.
02:19Like, we help people ship applications.
02:21We help people deploy all kinds of infrastructure to all kinds of places.
02:25And we have an adjacent project to it.
02:29Uh, so SST users get access to this thing called the SST console.
02:33And that is a local-first application.
02:36I mean, I'm gonna say local-first.
02:38There's obviously, like, a spectrum.
02:39I would say it's a local-first.
02:41The least local-first thing with that you could possibly have while still,
02:45I would say, embodying some of the characteristics, but my history with it,
02:49like most people or like a lot of people, I guess, uh, it started with, with Linear.
02:54I came across.
02:56The product probably like 2018 or 2019 somewhere, somewhere around there,
03:00probably 2019, something like that.
03:02And I found them fascinating in a few dimensions.
03:07One, their attention to detail was just kind of outrageous.
03:10Like there's all these little details.
03:12Outside of local-first stuff, just these details that are in there that, you know,
03:16they're, they're like real craftsmen.
03:17They care about, uh, every little aspect of their product.
03:20I found them really interesting from a business perspective because they
03:24entered the most crowded and most cliche space you can possibly think of.
03:28Everyone has had the idea of, I hate my project management tool.
03:32Like I should build my own, uh, the most boring, cliche,
03:36non innovative idea possible.
03:38They enter that space and they absolutely crush it.
03:40Like no one really could have predicted that.
03:42I think you would have, if you just heard that idea, you're just
03:45been like, whatever, and they did that purely from this aspect of.
03:49Really excellent quality and performance.
03:52And these are things that people will love to say, like, oh, the user doesn't care.
03:56People, performance doesn't matter.
03:57Like, you know, they'll try to say that it's something that you can do later.
04:00And this is a great example of a company that's kind of violating that narrative.
04:05So I find them really fascinating.
04:07And I got obsessed with just digging into how They built their stuff
04:11initially from like a UI perspective.
04:13But then I was like kind of looking into how all this, how everything
04:16is super responsive and instant.
04:18And I started them so hard to the point where I think I was really
04:21convinced at some point that I knew more about their system than
04:23anybody that didn't work there.
04:25Like I understood like their exact protocol, like how
04:27they sort stuff locally.
04:29Uh, I kind of just kept going back to it to refer to it.
04:32And around the same time, my wife and I were starting a new
04:34project in the healthcare space, and this was a productivity tool.
04:39So it's the type of tool that people log into the beginning of the day, use it
04:43all day until they finish their work.
04:45So these are the places where I feel like the performance
04:49aspect is really understated.
04:52When you're using an app every single second of the day to do your work,
04:57There's all those little paper cuts where something takes a little bit longer
05:01to load, or there's like a spinner.
05:03These do weigh on you.
05:04If you talk to the user, they probably won't articulate it.
05:07But if you ask them the question, does it feel like a joy to do your work?
05:11Or does it feel draining to do your work?
05:13And they're going to say draining unless you push things to this degree.
05:17and this never shows up in like typical user research or like user
05:20feedback or any of that stuff.
05:22So because we were working on something in this category, I
05:24was like, okay, we have to do it.
05:26We have to like set the, meet the same bar that Linear met.
05:29And that's kind of when I started digging into what are all the
05:31different ways that we can enable this.
05:34And we started from like a JSON API using Orbit to like replicate
05:39the data locally, to GraphQL and Urql to do something similar.
05:44Um, and then we eventually ended up on Replicache after,
05:47like, trying a few of those.
05:48Uh, we also tried, I think, RxDB at some point.
05:52Because we knew that, yeah, we want to have almost every operation
05:55happen locally, if possible, so that the feedback is instant.
05:59You know, searching, and this is in the healthcare space, so searching
06:02through patients should be instant.
06:03Loading up their information should be instant.
06:06Even if we had a really large data set on the server, In terms of like,
06:10a single business might have, you know, tens of thousands of patients.
06:14An individual doctor is only seeing a small subset.
06:16So having the ability to like, partially sync the data that
06:19we know the user cares about.
06:21So we spent like, through the course of building this product,
06:24we tried so many different setups.
06:25And we've probably spent two years of learning and trying how to do these
06:31patterns before we landed on something where, one, like the tools, like
06:35I said, we ended up on Replicache.
06:36Replicache is a tool that we liked, and two, like, As people building products,
06:40like we understood how to like, really take advantage of it, how to structure
06:43things and where to pay attention.
06:45So that product is called Bumi.
06:48Uh, we actually ended up deciding to pivot away from it.
06:50Uh, like we have, we have some customers, but it just ended up not being a
06:54market that was particularly large.
06:56And so we wanted to switch to something that was a lot more,
06:59like, wide, like anyone can use.
07:02And something that we personally would use, I found that any product
07:05I build where I personally use it, it just comes out like 10 times better.
07:09It's just way easier to understand the problems and be motivated to fix them.
07:13So we're working on a new product called Radiant now.
07:15And that is a personal finance application, which again,
07:18there's thousands of, very similar to the Linear story.
07:21But we really believe building, like, a very power user
07:25productivity focused version of it.
07:27There's like interesting room in the market for that.
07:30So the one other thing just to kind of cap off the story is, uh, so between
07:33those two things, uh, working on SST, we also kicked off a new project there, the
07:38SST console, which I mentioned earlier.
07:40Kind of a similar story where this is a tool that you use alongside
07:43your day to day development.
07:44You're using all the time.
07:46Having every single thing be fast really makes a difference in the end
07:51feeling that users have of the product, so we decided to go with the same kind
07:56of local-first ish model for that.
07:58And that one is completely open source.
08:00We were really public about building it.
08:02I think a lot of people were exposed to the idea of This pattern, and we've seen
08:07people like, kind of take that project and like, use a basis, use it as a
08:12basis for things that they're building.
08:13So yeah, I think for me it's always been about delivering
08:17a much higher user experience.
08:19I really feel like at some point the web was really focused on how
08:25can we make the web feel native, and that was like the obsession.
08:28And for some reason that like, kind of went out of popularity, but I personally
08:33still care about that as an end user when I use products and they're slow and laggy.
08:37I want everything to be my browser.
08:39I like that and I want people building those things to care
08:41about those things because I'm just going to be happier as a user.
08:44And it's kind of been my.
08:45My reasoning to really like, you know, spread the word about this stuff.
08:49Yeah.
08:49Everything you've just said deeply, deeply resonates with me.
08:52I'm similarly also very inspired by, by the folks at Linear, how
08:56much value they put into the craft.
08:59I was actually just, uh, as a little anecdote, I was just having
09:03drinks last night, uh, with Julian from the, the, the Linear team.
09:08And we were also chatting about this and similar to what you've
09:11described as that it's so tricky.
09:13It never shows up in your user interviews, et cetera, that people say like, Oh,
09:18like I'm really annoyed that this button takes like 300 milliseconds.
09:22But if it was instant, then I think people will really, uh, share that.
09:26And it's basically like a, more of like a death by a thousand paper cuts, and
09:30it's too hard to enumerate the thousand paper cuts, but it's still kind of clear
09:35that the product is not very smooth.
09:37But once you really, once you're using Linear, then there is no going back.
09:42And this seems to be also still like a challenge in terms
09:44of communication for them.
09:46How do they articulate to someone who has not tried it out yet?
09:49What the difference is?
09:51It's that overall quality and, but I think they're doing a great job of
09:55just being sort of like the lighthouse example now of like what that next
09:59generation category defining product feels like and should be like.
10:04So I think they're, they've like bootstrapped their way out of that, that
10:07problem and it's very inspiring for me where I'm like my JIRA is kind of music
10:13apps where I am annoyed by the thousand paper cuts that you have in when you're
10:18using Spotify or SoundCloud, et cetera.
10:22So many of those supposed apps feel more like websites that really like
10:27Winamp was a, or iTunes back in the golden days, that was a much superior
10:32user experience to what we have today.
10:34We have maybe a richer ecosystem in terms of available music, but the actual user
10:39experience that has really suffered and I similarly also care a lot about how
10:46native can you make a web app feel like.
10:48And not just, end up with your ambitions on like a website level.
10:54So, uh, that deeply resonates.
10:56I think there is, it's both, uh, equally exciting to explore that from a user
11:00experience, what really drove you.
11:02But I think there's also a lot of potential from a developer
11:06experience point of view, where I think there's also so much stuff
11:11we just put up with as a developer.
11:12So I'm also curious to hear more on that, but yeah, you, you mentioned that you
11:18had a one to two years of explorations early on that, where you figured out
11:24how not to do it, I'd love to hear a bit more about those failed attempts.
A slower initial page load is worth it
11:28Yeah, so I think, the spectrum really was just us dipping a toe to
11:33then going further and further and further with how much is done locally.
11:36So, I think initially, it's, that sounds weird to everyone, right?
11:40Like, what do you mean replicate the whole data to the end client?
11:45Like, it's too big.
11:46Like, that can't work.
11:46Or like, what about this?
11:47What about that?
11:48What about that?
11:49Uh, so I understand the hesitation.
11:51But any like half step in that direction, it just kind of a gateway to like, just
11:55replicating more and more and more.
11:57Cause you just want more and more and more to be instant.
11:59So I had a very traditional mindset around it, which is, okay, we have an
12:03API, the API serves data and like, we're going to like cache some of that locally.
12:07And I think a lot of people are already doing this.
12:09Like a lot of stuff, like react-query like gives you this starts to like put
12:13you in that direction where just caching stuff and then like refetching, you know,
12:17when the window becomes active again, it kind of gives you some of this like
12:20real time local-first feel, but then you start to hit the limits with that, where.
12:25If you're like, if you're looking for stuff that's not literally in
12:28the exact view, you're then kind of round tripping with the server again.
12:32And I think the key thing to understand is, is if you're building an app that
12:37people are actually using every day, the initial load time is really not
12:42something you need to care about.
12:44The first time they load the app, like let's say they like
12:47log out or it's a new computer or whatever, they're setting it up.
12:49Okay, like maybe they're downloading a couple megabytes of stuff.
12:53That's going to be slower than You visiting some public website that's
12:57like optimized around like the initial load time, of course, but once that
13:02initial cost is paid, every single interaction that they have going
13:06forward from there is insanely fast.
13:09And that trade off is so worth it for apps that people actually use as a joke.
13:13I like to make out is that the web has become so obsessed with
13:17optimizing for websites where people visit and leave as fast as possible.
13:22I'm like, If you're working on something like that, totally get it.
13:25Like totally get all the, the SSR stuff.
13:27Everyone's obsessed with all the, like the infinite levels of like CDN caching
13:31and the little optimizations there.
13:32I totally understand that, like minimizing bundle size, all that stuff.
13:36But a lot of people work on SaaS products.
13:38Most of the products that I use every day are not, don't fit in that category.
13:42I'm using them every day, like just preload stuff for me.
13:45And I feel this way about some of the biggest products, right?
13:48Like think about GitHub.
13:49I'm an open source developer, like, my day to day job is
13:52maintaining open source projects.
13:53I'm in GitHub all day, clicking through issues, looking through
13:57commits, looking at PRs.
13:59It is so frustratingly slow how almost every single interaction
14:04results in like a page load.
14:05GitHub knows, okay, you're not going to send me all of GitHub to me locally.
14:10But you know there's these three repos I work on every single day.
14:13Sync that locally, sync that optimistically.
14:15Like that would save me so much time and frustration and energy.
14:19And actually scratch that.
14:20It's not really about the time.
14:21It's really about the energy for me.
14:22You can spend four hours doing work that saps your energy and four
14:27hours where you feel empowered.
14:28And to me, like good apps like this.
14:31I like feel super empowered and it's not sapping my energy.
14:33I'm not drained after the four hours.
14:35I'm like ready to go on to my next thing.
14:37Right.
14:37And yeah, some of these biggest apps that are productivity apps are so
14:40built like traditional websites.
14:43Definitely.
14:44Yeah.
14:44I mean, the, the use case that you've mentioned in regards to
14:47GitHub is, is an excellent example.
14:49Like for, like you have those.
14:52units that are really self contained, most repos don't have hundred of thousand
14:58of issues it's really easy, like takes roughly the same amount of data that
15:03like your initial JavaScript bundles took to just download the entire, thing as a
15:08SQLite database or like in another format, and then just have it there available.
15:13Since you're navigating so much within the scope of a GitHub repo, whether
15:17it's Between GitHub issues or going to like a pull request or something
15:22and whatever paper cuts you experience there, it really lowers your effort
15:27of like wanting to go the extra mile.
15:29Whether you want to respond to someone's like, in a GitHub comment.
15:33I think, uh, Jamie Kyle, actually, I think he ran a couple of experiments
15:37there that's literally faster on GitHub to open a new tab for a link and have,
15:43get the server side rendered stuff than dealing with like the, The, the rail
15:46style in navigation on the existing site.
15:50And that speaks exactly to, to the symptoms that you've,
15:53that you've described.
15:54I will also call out a project.
15:57I don't fully remember the name anymore, but someone on Twitter, I
16:00think was working on, on exactly that, like a little GitHub client that is
16:05local-first inspired, that pulls down your data that you're dealing with to
16:10make exactly these interactions fast.
16:12Maybe you know the name.
16:13Yeah, so I actually tweeted asking about this.
16:15I remember seeing it and I couldn't remember it.
16:17And I think it was, uh, by Devin, the Parcel JS.
16:20Yeah, so I saw him messing around with that.
16:22I don't know if he ever, like, finished it or released it or anything, but
16:26yeah, this is so desperately needed.
16:29GitHub isn't going to do it, I don't think, because it's so outside the
16:32scope of how their system works.
16:33But just someone, please, just build a thing that syncs the
16:36issues and PRs optimistically.
16:39And you're going to save me so much.
16:40I'll pay for this product easily.
16:42I don't know how big the market is for people that care this much, but it
16:45doesn't seem like that much work because it's just a single repository view
16:48and some of the stuff that's in there.
16:51And you could totally do this.
16:52Yeah.
16:53This is kind of what I was saying before.
16:54I'm mostly speaking as a developer, like building these things.
16:57But the end thing I care about is as a user.
17:01I just want more of this stuff out there in the world.
17:03So I'm not as frustrated.
17:04I definitely agree.
17:06And like, I applaud you for like going that adventurous path and that extra
17:10mile with SST console, since I think you had the right intuition there and it is
17:16paying off in terms of just how fast that feels to use and how much, like you say,
17:21like it no longer drains your energy.
17:23Yeah.
17:24It gives you energy using that.
17:26And once you had that experience, you'd really like every loading spinner
17:30that you see is so much more painful afterwards when you're like using,
17:35for example, the, Cloudflare console, it's like the same thing there.
17:38Like you're within a project , you have that many deployed workers and
17:41you just want to navigate between that.
17:43It's fine that my logs stream in.
17:46But all the metadata around that should just be instant.
17:49It's a tiny amount of data.
17:52And like the majority of apps, if you really look at what data people are
17:55constantly going between, it is so small.
17:58So yeah, you figured out like the, the patterns early on or rather that you've
18:02realized, okay, you started with a bit of caching, a bit of more caching, a
18:06bit of more caching, and you didn't quite find the right line to draw.
18:10So you just, okay.
18:11We're going to just bring over all the data.
18:14Did you have other sort of learnings where you had to rewire your brain?
Local-first makes app development simpler
18:19Yeah.
18:19So I think, uh, one other middle step we had was we tried it through GraphQL.
18:24We weren't particularly interested in the GraphQL part.
18:28It was, it just happened to be that, uh, Urql, the GraphQL client.
18:32It implemented a lot of, uh, the local-first stuff like you could
18:37replicate the whole database locally and because GraphQL has a
18:40nice, idea of like relationships between objects, the data format
18:44locally could be pretty intelligent.
18:45like, downloaded 1 thing, it knows how it's related to another thing.
18:48So if you query it from a different path, it can, like, resolve it locally.
18:52So there's just some clever things that it did.
18:54And we thought that was really cool.
18:55But what ended up sucking was we didn't really like GraphQL.
19:01And everything you did, even local operations, required GraphQL as input.
19:06which again is fine.
19:07It's just, it just wasn't really clicking for us.
19:10And again, it still had this, uh, There was a limitation of like, it
19:15wasn't really meant or initially designed to have all data locally,
19:19so it's all like, there's always like some stealing or some performance
19:22issue or something you run into.
19:24So when we went all in on having, okay, like we, the system is primarily
19:28designed around syncing the data locally.
19:30What we found actually, and I think the Linear people talk about this too, is.
19:34The developer experience around this became a lot more simple.
19:38So my wife, who I work on this stuff with, she is not an engineer.
19:43She does everything else outside of it.
19:44But in the past couple of months, we're like, why are we drawing that boundary?
19:48Just learn how to be more hands on.
19:50And so she's been learning like how to actually like write the code
19:53and build these things and she's making like fantastic progress.
19:56One of the things that's been crazy helpful is.
20:00All the data's just there locally.
20:02So for her, even though she's a beginner, it's such a simple model.
20:05She's not like figuring out the round trip with the server, like syncing all that.
20:10Like, I handle all that, and I make sure, like I figure out how the data looks like
20:14on the back end, and I make sure it's all synced correctly to the front end.
20:17From there, there's not all this weird like, loading states, or like fetching it,
20:21or like just a whole bunch of complexity around getting data back and forth.
20:25It's solved in one part of your app, and then you never have to
20:28think about it anywhere else.
20:29So just from like a team productivity point of view, like she can build
20:33any feature she wants, even if I didn't like explicitly think about
20:37it from the backend point of view, because she has all the data locally.
20:41She's like, I want to create a view that searches through this set of data.
20:43She can just go do that.
20:44All the data is there.
20:45Very, very straightforward.
20:47And it's actually wild how much of a productivity boost that has on
20:51your team, because you're not like constantly building these like back
20:54and forth with every new feature you're not rebuilding another way to
20:57like sync that data back and forth.
20:59and it's been amazing.
21:01That's so liberating.
21:02Uh, we talked about this also in the recent episode with Kyle, who drew the
21:06comparison of like going from jQuery to React where React freed you up of like
21:11that manual view maintenance and now going from like the, the manual state
21:15transfer across different environments that frees you up of like that data
21:20management and you can now actually.
21:22Focus on what matters most, like building a great user experience
21:25and putting the effort into the pieces that do really matter.
21:29And that simplification that is just so, so hard to overstate how nice that is.
21:35And I think that also unlocks a whole bunch of like new.
21:38tooling.
21:39So for Overtone that I co developed with the project Rffle, or now called
21:45LiveStore, it's always been a first class citizen to have great dev tools.
21:49And one of the parts of the dev tools is to have a data browser in there.
21:52So it basically feels like a Google spreadsheet and really it
21:56also acts as a Google spreadsheet.
21:57You have, you have like visual view.
22:00on all of your data, if you change something such as like a playlist
22:04title in that data browser, it like automatically updates in your app.
22:09And there's no question of like, Oh, do I not need to like
22:12send this to this REST request?
22:14But do I need to also like, Invalidate this in Redis.
22:18No, you just like set the data and there it is.
22:21Yeah, that's great.
22:21I mean, a local data route is actually something that we're definitely
22:24missing, but that's a, yeah, it's like it enables so many things like that.
22:29Just the debug ability and observability of what's going on and just being
22:32able to change something in one place and have it update everywhere, like
22:35in your view and in the backend, it's just so, it's so much simpler.
22:38And it's weird because I feel like apps used to kind of work this way.
22:42Like when I got started, I was building desktop applications.
22:46And I guess there wasn't really a cloud component in some of
22:49the initial things that I built.
22:51And they were this simple because the data was just local and like
22:53you'd hit a button and you like mutate the data and it's it's there.
22:56So yeah, to me it feels like returning to a simplicity with like
23:00much more power and capabilities that we didn't have back then.
23:03Exactly.
23:04Plus we now also get the power of the cloud for collaboration and
23:07like a lot of the, the nice pieces.
23:10But I think there's just been an over investment over the last 10 years
23:14into having everything be so cloud centric that like you built like
23:19even a local calculator probably as like a remote rendered server app.
23:24And, I think now also bringing more investment into kind of back to the roots,
23:30uh, in, in this way of building, building apps, I think this will also help more
23:35people who are not quite as adventurous as you are to, to really explore this before
Local-first data patterns
23:45Yeah, and like there are, like a lot of stuff becomes simpler.
23:48There's some new stuff you have to learn, of course, like with
23:50any new paradigm, there's, things that are a little bit different.
23:52I think some of those involve things like, so in our case, in the Bumi example,
23:57we unfortunately had customers that had too much data, where it wasn't as
24:01simple as just syncing it all locally.
24:03So we have to think of like some new kind of like UX related patterns where
24:08we kind of optimistically sync stuff that we think the user will care about.
24:12So like the first time you visit a patient, it might take a little
24:15bit to load because we didn't sync all the patients locally.
24:18We do sync like a shallow version of the patient locally for everyone, so they can
24:23search through all of them really quickly.
24:25But to get into the full details, like you might not.
24:27That's too much data to send to everyone.
24:29So the first time you go there, it'll be a slow load.
24:31But from that point, we kind of flag them as, Oh, this
24:33user cares about this patient.
24:35And from then on, we'll constantly send them updates.
24:37If they haven't visited the patient's profile for like two weeks or
24:40whatever, then we'll kind of unflag it as something that they care about.
24:43These are like new patterns that, you know, they don't really
24:46exist in a traditional app.
24:47But this mixture of local and cloud, you can get pretty far with tricks like that.
24:52And we kind of have to learn some of those tricks and some of those ideas.
24:55Because we have a whole like We have, I forgot what we called it, but
24:58it's like, uh, We have like a system where you can easily flag stuff as
25:02a user is interested in this thing.
25:03And if you flag it, it starts getting synced and then it'll get unsynced
25:06after some window that you specify.
25:08So we kind of have to like, you know, think about that and, and
25:10create a framework around it.
25:11But that's one.
25:12The second thing is like, obviously handling, And this
25:15isn't unique to local-first.
25:17Anywhere you're doing optimistic things, obviously there can be
25:21errors that happen on a delay.
25:23Again, it depends on the type of application.
25:24Like a music player, probably, the syncing is probably like pretty
25:27straightforward, but for something that's Looks more like a traditional SaaS app.
25:32There might be sources of truth that can't be validated entirely locally.
25:37So you'll end up with situations where the user does something, then goes
25:40away, then the error shows up later.
25:42And like, you need like a whole different UX pattern when you can't block the user.
25:47It's worth doing because 99 percent of the time they don't hit that error.
25:51So it's good to let them move on.
25:52But you have to handle a case where, where they do.
25:54So there's different problems that show up, but again, it's all in the name
25:57of a better experience to the user.
26:00So totally worth it.
26:01So, let's say you have some kind of.
26:03You can create a new field that needs to be globally unique in your system.
26:06So let's say, uh, I mean, we can just use Linear as an example.
26:10Like, you can create a new project in Linear, but the name of the
26:12project needs to be unique.
26:14there's an impossibly small chance that you create it and you move on, but someone
26:19had created it at the same time, because they thought it was their job to do it.
26:23And there's like an issue, because your write maybe got rejected.
26:26in a typical UI, when you create the project, you would see a spinner.
26:31Spinning.
26:32Okay, created.
26:33Because you have a spinner there, you can, like, make sure stuff gets written
26:36correctly and then you don't let the spinner come back till you know for sure.
26:40It's good.
26:41Um, so anywhere with this like unique feel type of situation,
26:43we run into this problem.
26:45Our fix is actually pretty simple.
26:47We just have like some kind of like context thing of like pending
26:50stuff that hasn't been confirmed.
26:52And if it comes back with an error, we just pop up a toast that
26:55brings them back to the original.
26:57We, like, reload that original content.
26:58If they want, they can click back and go back to where they were.
27:01And, like, you know, change the issue that they had.
27:05So I think we found that pattern to work pretty well.
27:08Obviously, it's like, the example I gave is really stupid.
27:11Like, no one is ever going to run into that.
27:14There's some examples that are a little less stupid, where it is reasonably
27:17possible that it could happen.
27:18But we found this idea of, like, preserving the context of the
27:22UI and bringing them back to it.
27:24If the error happens, they can opt to go back.
27:27We found that to work pretty well.
27:28Yeah, I think that's a very elegant solution for this.
27:31I mean, another possibly even more aggressive solution to this
27:35would be to say to gate this feature behind being online.
27:39And to actually like establish some notion of like a global transaction for
27:44that and, only let the user pass through this intentional bottleneck if that
27:49has happened, but the way how you've designed this in a asynchronous way.
27:54I think it's also very elegant.
27:56but I think this is the nice thing that like local-first affords you or forces
28:01you to do is like, it frees you up from a whole bunch of stuff you no longer
28:05need to do, but it really forces you to think about carefully, what are the
28:09domain requirements of your specific app?
28:13And if your domain expert from the app says like, Hey, this is
28:16what's really important here.
28:18There cannot be two project names with the same exact name.
28:23Then like you can actually put in the extra efforts to enforcing that.
28:27And this is what makes the app worth it later.
28:29Yeah.
28:30Yeah.
28:30And it's, yeah, it's not all or nothing.
28:31You can opt in.
28:32So the thing that you said, we are in the SC console.
28:34We do that when you're creating a new workspace, we actually do have a
28:37spinner there because it's like weird to like, Create a new workspace and get
28:41kicked back 'cause the name was taken.
28:43So yeah, we, we hold you there And that's like, you know, a more
28:45traditional experience and that's fine 'cause that's like a very small
28:49percentage of the app where you're like creating a new workspace.
28:53You do that once when you sign up and you never do that again.
28:55So yeah, you can kind of granularly pick where you want a more traditional
28:59blocking approach and where you want an optimistic approach.
29:02And I think a lot of the people that are maybe skeptical of the local-first
29:05thing, I think they tend to imagine it in these extremes of like.
29:09You have to sync all of your data and obviously that won't work.
29:12Or like you have to have everything be optimistic and obviously
29:14everything can't be optimistic, but you can really pick and choose.
29:18It's more about what you default to.
29:20And then you opt out of It's good to default to optimistic first.
29:23Cause that's, what's great for the user.
29:24Right.
29:25I think in the, in your context of building SaaS apps, I think there's
29:29kind of layers to this entire thing.
29:31There's like the global system.
29:33That you're still in control of.
29:34That global system is probably not local-first by all the ideals, but once
29:40you create an account or once you've created a project, and now you enter like
29:44a smaller scope of that overall system, and that now is very much local-first
29:50because this is where it actually matters.
29:51It's okay if your users sign up.
29:54takes half a second to load.
29:56But once you're in your productivity environment, this is where you
29:59want to really have unlock the benefits that local-first gives you.
30:03Yeah, exactly.
30:04The data, what is the day to day workflow like?
30:06And that should be, that should be, you know, an excellent experience.
30:09I think the other area, and we talked about this a little, is there's also the
30:15desire for apps that don't die because a company went out of business or like,
30:20you know, They were forced to find a business model that didn't make sense
30:23for the idea that they were working on.
30:25And I think this does make a lot of sense, I think.
30:27If you think about something like a, like a video game.
30:30I mean, video games are different now, but like, you know, there was a time
30:33where you would buy the video game.
30:35It was a finished product, and it was on, like, a physical thing, and
30:39you could just run it and play it.
30:41And.
30:42You had that forever.
30:43So, but I mean, now you have like some games that require you to be online
30:47or it's a, it's a hybrid of both.
30:48And like, you can imagine how at some point this game won't be playable anymore.
30:53And that's happened to a few things.
30:55I think people feel that way about applications as well.
30:57And I totally get that.
30:58I personally don't work on anything where that's like the critical
31:02burning desire where like, you want it to like really run locally.
31:06You want, you care about the privacy, you care about whatever.
31:08I like totally get all of that.
31:10It just hasn't intersected with like the areas that I focus on.
31:13So for me, it's been more about, uh, just the experience side of it.
31:18And I think the reason is a little bit tricky to go to that extreme in SaaS.
31:22is a lot of like a portion of your value is in the end experience.
31:27And like we talked about, I think people are under delivering there,
31:30but usually it's also tapping into some kind of bigger data set or bigger
31:35capability that can't really run locally.
31:38So it's usually a mix of the two things.
31:40So I typically will have to mutate the data outside of
31:43the user interacting with it.
31:44So if you look at something like, uh, like Radiance, so this is
31:47going to be a personal finance app.
31:49You can totally build a fully local-first version of this
31:51that runs entirely locally.
31:53That whoever's building the app, it can be totally encrypted where they don't even
31:55have access to seeing any of this stuff.
31:57And there's like value in building something like that.
31:59But, you know, with all these advancements in AI and LLMs, those can actually impact
32:05Personal finance apps a lot in terms of like making sure that data is cleaned
32:08up correctly, auto categorizing, like all the things that sucked historically
32:11about these applications, LMS have a lot of potential to fix that, but
32:17there's not really a good way to do that in a local-first way, at least today.
32:20So that's why for us, you know, for building this thing,
32:23it's not going to be this.
32:25thing that runs entirely locally because we still want the ability to
32:27like process your data using tools and technologies that, you know,
32:32unfortunately can't run locally today.
32:34Yeah, I think you've touched on a couple of really interesting points there.
32:38So the, I think right now, the canonical definition of like, what is local-first
32:43software is as according to the Ink and Switch essay that lays out the seven
32:48ideals of local-first and I think you're, You're, nicely sticking to the first four,
32:53which is like about the loading spinners and that it works offline and so on.
32:57And I think what you've just hinted at, what you don't do yet is what
33:01local-first calls like the long now that your app like lives on, even if the
33:07creators are no longer working on it.
33:09And that's very understandable.
33:11That takes a lot of time to, and effort to put into.
33:14And given that you just have so much time to work on the app,
33:18that is not your highest priority.
33:19However, what I think is still nice and a glimmer of hope there for the entire
33:25category of local-first inspired software is that if at some point you say like,
33:30okay, I'm winding down development on this app, then you could still much more
33:36easily to put in a bit of extra effort.
33:38to now round up the project in a local-first way.
33:42I think we've seen a really nice example of that with another personal finance
33:46app called Actual Budget by James Long.
33:49And so as he no longer had time to work on that project, it was so much easier now
33:56to transition the app from something that he hosted as a cloud service to something
34:00that people can just run by themselves.
34:02If you build like those monstrosities of like giant Kubernetes cloud things,
34:08it's really, really hard to like, tell someone how to easily just download a DMG
34:13and run this on your MacBook, whereas if your app is local-first to begin with.
34:18Then, I think it's much easier to repackage the app that you've built.
34:23And you can trim away a lot of like the multi tenant stuff that
34:26you need about SaaS and just package the, the productivity
34:30aspect of the core of your app.
Self hosting
34:39Yeah, I agree.
34:40I think so.
34:41And with Radiant, we're actually, so because we can't.
34:44Do this thing where it's like end to end encrypted and because of
34:46what, what our goals are, instead, we're making it dead simple to
34:51fully run the whole system yourself.
34:54If you care about hosting yourself and you want all the data and a big part, and to
34:58be honest, that's a lot of what SST does.
35:00SST helps you ship very complex software multiple times in multiple environments.
35:05and so, because Radiant is an SST app, it is very easy to point it
35:09at your own private infrastructure and say, I'm just going to have
35:12a self hosted version of this.
35:14And it's, and we're making sure it's like, As simple as it can be to do
35:18that, and get as close to, like, using the hosted version because there's
35:23like some weird benefits of that.
35:24Like, so this version that we're building is going to be mostly built on Cloudflare.
35:28If a lot of people end up self hosting it, that's great because
35:31Cloudflare is paying for the usage.
35:33Like, The free tier is coming out of each individual's deployment.
35:37They're like self deploying it into CloudFlare.
35:39And that's like an interesting model for, I don't think for radiant, it's
35:42like particularly interesting, but if you look at, um, there's another
35:45project by, uh, Ben Vinegar, he works at Sentry, called CounterScale.
35:50So this is a classic, like Google analytics type product, right?
35:54It does like this web analytics, the basics, and it's very early on.
35:57But it's not a hosted project.
35:59It's just something that deploys into your own CloudFlare account.
36:01So he can have a million users using it for free without ever
36:05really, you know, paying for that because, you know, CloudFlare is
36:08much more set up to offer that.
36:11I'm very interested in that model.
36:12Uh, cause I think for a lot of infrastructure pieces
36:14like that, it is a nice.
36:16To have it alongside the rest of your infrastructure.
36:18I worked a lot in healthcare environment, which has a lot
36:21of compliance requirements.
36:23And oftentimes I couldn't use the tool I wanted to use because it
36:26wasn't hostable in my own environment.
36:29So, um, we're pretty excited about like letting people do more of that.
36:33I love that.
36:34And I think this is like intuitively.
36:37It should be easy to self host your own software, like whether it's like
36:42some company running it or whether I just like take the software, put
36:46it on my Raspberry Pi, put it on, on Cloudflare or AWS, but in reality,
36:52that's very much the exception.
36:54I'd be curious whether you can share a bit more of like the reasons that
36:57you see why that's so hard and how you're trying to make that easier.
37:01Yeah, I think, uh, it's funny because there's a weird alignment
37:05if you think about this.
37:07We are a small team.
37:08If our system is really complicated to run, that sucks for us.
37:12If we can make our system really easy to run and really low overhead and we care
37:15about that more than everything, it kind of starts to look like something that's
37:18easy to self host by anyone, right?
37:21So I think for us, like, a lot of times we'll choose architectures that look
37:24weird because they're like, Oh, that looks like the fourth option on the list
37:28of the ways they could have built it.
37:30But it's because we really, really care about, low operation overhead long term.
37:38So even if it's like, you know, 20 percent harder to build up front, if
37:41it results in like less babysitting on our end, we'll like choose that option.
37:46And it's because we're very committed to continuing to be a really small team.
37:49And so we'll, we'll end up picking those options and those options happen
37:52to align with like, what's, what's simplest for, for the end end user,
37:57if they're self hosting, I will say like there is a version of doing
38:00this, which we don't do, which is.
38:03Building your stuff in the most, like, neutral way possible, so it
38:06can run in literally any environment.
38:09I definitely get that, but you do end up having to run a lot of
38:14infrastructure on your own to, like, get any complicated application working.
38:18If you do it in a totally neutral way.
38:20We kind of picked a middle ground where it's like, we do rely a lot on, like,
38:24in this example, like, we're going to be using CloudFlare, we're going to be using
38:28workers, we're going to be using their queues, we're going to be using their
38:29PubSub, all the CloudFlare native things.
38:32So, yeah, if you want to go take that and run it inside, like, just
38:37a standard server you have, it's going to be a little bit challenging.
38:40And like, there are adapters and stuff, and you can figure that out.
38:43But we're starting with just making it runnable in your own cloud environment.
38:49So you can sign up for a Cloudflare account and run it.
38:51I know that doesn't like hit the exact extreme of like being able
38:54to fully run it yourself, but we think it's like a nice middle ground
38:57for a lot of companies, right?
38:58Companies typically are already using some form of this.
39:01Getting this stuff deployed into their own account.
39:03I think it works well.
39:05What's weird is you ask, like, why isn't this more common?
39:08I think it's actually common in this weird way that people don't expect.
39:13A lot of companies build SaaS software, right?
39:16They'll build like, I don't know, let's say, let's take some random common
39:20thing, like Auth as a service, right?
39:21Like, I'm going to build Auth as a service that people can use.
39:25And they initially launched that as like a hosted product.
39:28And nobody uses it except for people that have no money.
39:32So they have like a lot of users, but you know, these users don't pay a lot.
39:35They start to try to move up, up market.
39:38They end up with bigger companies, you know, medium sized
39:40companies, enterprise companies.
39:42They'll all love the product, but refuse to use a hosted service.
39:46So then they're forced to figure out how to make their stuff run
39:49inside the customer's AWS accounts.
39:52So if you do look at a lot of these companies, they kind of
39:54do have this hidden, like thing that they eventually figured out.
39:57I think companies should realize they're going to end up in this place anyway.
40:00Like it's very hard to build a big business purely off of a hosted thing.
40:04Like some people do it when you really have like a large market,
40:08but oftentimes you're forced to.
40:09Bring yourself inside someone else's environment.
40:11So I think one way or another, you're likely to hit that.
40:14So it's good to plan for that upfront and assume that you're going to run into that.
40:17And we, because we're like, We're more in the infrastructure space.
40:20We kind of expected that from the beginning, which is why we care a little
40:23bit more about making all that possible.
40:26So let's imagine I want to follow this paradigm for Overtone.
40:32And I do think that Cloudflare could be a very interesting fit for that in
40:35terms of the modern primitives that it provides, so what would I need to do as
40:41the application developer of Overtone who buys into that vision and says
40:45like, Hey, I don't want to operate like the cloud thing for that, but I want
40:49to empower every user to deploy their own for the benefits that it provides.
40:54What would I as the application developer need to do to make that happen?
40:58And then also follow up question.
41:00What does someone who wants to deploy that Which sort of additional stuff
41:04do they need to deal with as opposed to just using something like Spotify?
41:08Yeah.
41:09Yeah.
41:09Cool.
41:09So I think, I think the simplest way to think about it is how hard is it you
41:13for you to spin up a staging environment for your own application, right?
41:17You want to create an exact copy of your environment, but you
41:20know, just the staging version.
41:22So this requires bringing up all the same infrastructure.
41:24It requires like, you know, running your database migrations
41:27to get the schemas running.
41:28Um, requires a bunch of things.
41:29And, you know, the obvious thing is you should be using infrastructure
41:32as code to help you do this.
41:33You define all your infrastructure as code so you can point it at different
41:36environments and run entire copies of it.
41:39That's like the bare minimum.
41:41If you yourself can quickly create another environment for yourself,
41:45you've kind of solved the problem.
41:46Now someone else can follow those same steps.
41:49Where they're just cloning your project and running.
41:52You might be using Terraform, you might be using SST, whatever it is.
41:55Uh, you can do a thing, deploy with your credentials.
41:58And the same thing ends up in your account.
42:00Where this is a little bit challenging is updates.
42:03So obviously, you know, you have new versions.
42:05People can clone and redeploy, whatever.
42:07But there's sometimes operationally challenging updates.
42:11Like you might have like a schema change.
42:13You might have, uh, like data needs to be migrated.
42:16So, ultimately, the thing to always go back to is how do you make it
42:21easy for your own team to do that?
42:23Are there programmatic ways of doing all this?
42:25Or, like, if you need to do ad hoc random stuff and that's part of your
42:29workflow, it's going to be annoying for your end user to self host because
42:32then you need to, like, send them the instructions, they need to do it,
42:34they might, like, do it incorrectly.
42:36So, if everything is tracked in code and is automated and is
42:39programmatic, It's good for your team.
42:41That's good for the end user.
42:43and for an end user, in terms of what they should expect, if you are
42:46using some version of the cloud, you should hope that the thing you're self
42:51hosting is taking advantage of as many managed services as possible, right?
42:55So I had this issue with PostHog.
42:57So PostHog is an open source analytics tool.
43:00And when I was exploring it for my healthcare thing, I was like,
43:02okay, we'd have to self host it.
43:04Let me go look at the first self hosting steps.
43:07Step one, set up Kubernetes.
43:09Right, immediately there, I'm like, I like, found a way to finally free myself
43:14of Kubernetes for my main application.
43:16I don't want to like go, have to go manage a Kubernetes cluster
43:19again, just for this thing.
43:21So you should hope that, you should pick tools that use
43:25managed, versions of these things.
43:27That's why, like, we typically focus a little bit more on some of the
43:31serverless stuff, because it's very easy.
43:33If our app just runs as a Lambda function inside of someone's
43:37AWS account, or as a Cloudflare worker, there's almost no overhead.
43:41You're not like, you don't have to like set up like Datadog
43:44to like monitor the memory and like scale this up, up and down.
43:47It sucks to do that for like a small tool that you're adding to your project.
43:52So we try to make use of managed servers as much as possible so that the end user
43:56doesn't have as much operational overhead.
43:59and again, some people are willing to do that.
44:01It's just, uh, it's obviously a spectrum with all of these things.
44:04I do think it's a double edged sword while it like really takes away that operational
44:09burden and operational overhead.
44:11It's not just about, uh, deployment cycles and like the update cycles of the app
44:17that you're deploying, you potentially also need to update a, like from database
44:22version A to database version B of like just a database server that's running or
44:26like your analytics server or whatever.
44:28So that certainly takes a lot more effort.
44:31However, on a longer time horizon, if you do rely on managed services,
44:36they might just at some point send out a notice and say like, Hey, next
44:40quarter We're shutting down like that plan that you're relying on.
44:44So you're also in some regards might be building on quicksand.
44:48I think the, the larger a services such as Cloudflare, I think the
44:53chances that the rug is being pulled underneath you are probably lower.
44:57But it's always a double edged sword.
44:59And so my preference typically is in terms of the architecture that I'm using
45:05is like to go as simple as possible.
45:07This, for example, why I'm also very drawn to SQLite and I love the, all
45:11of the, the new tooling being built around SQLite since SQLite that's, no
45:16one's going to take that away from me.
45:17It's just like a little file.
45:19That I can put on a SD card or whatever.
45:22And, uh, that's still gonna like similar to that computer game from like the 1980s.
45:28that's still gonna work, in, in the future.
45:30And I think that's a great way to preserve data and you can
45:33still do so much with that.
45:35So I think that's sort of like a third option, uh, instead of
45:39going with like hosted or, Very scary self hosted infrastructure.
45:44If you make the self hosted infrastructure just that simple to
45:48rely on something like, like something that's almost serverless by default,
45:53like SQLite, I think that's a, that's a very attractive idea for me.
45:57Yeah, no, I agree.
45:58And with everything I'm saying, it's always like you have
46:01to exercise your judgment.
46:02I'm speaking from the things that I typically have worked on and
46:05I think this is where we landed.
46:06but yeah, if I was working on something that had different requirements,
46:09like, yeah, having like the simplest approach, uh, makes sense.
46:13The only reason that we have to do this is because we work on stuff
46:17that is like one of our tools is.
46:20Like, uh, like issues, like, kind of like how Sentry offers,
46:23like, issues that extracts.
46:24So we need to process, like, a large amount of logs, uh, because
46:28some people have, like, you know, like, billions of invocations a day.
46:31So it's not the type of thing that we can really simplify, like, we can't
46:34just give you, like, a single container.
46:36And this, because that's going to get overloaded very quickly.
46:38So the options for us are some crazy Kubernetes thing, or we
46:42just take advantage of AWS Kinesis and all these things that are
46:45built in that are lower overhead.
46:47Um, but, you know, if those weren't my requirements, I would
46:49probably opt for something similar.
46:51And yeah, at the day, it always just comes down to like, have good judgment.
46:55With whatever you're doing.
46:57Yeah.
46:57I think it's just as web developers, we're just so like in, in our like dependency
47:04fury in a way where like, we just like npm install this, npm install that, and
47:09we also not just package dependencies, but we also like add infrastructure
47:14dependencies left and right to something, I think is a big contributor, contributor.
47:19Why the long now aspect of local-first software is so hard to achieve.
47:24So I'm always, uh, trying as hard as possible to avoid dependencies,
47:29whether it's package dependencies or whether it's like infrastructure
47:33dependencies as much as possible.
47:35But it's always a trade off since they do sometimes can
47:38really save you a lot of time.
47:39Yeah.
47:40Yeah.
47:40I think for us, we kind of land in this middle ground where
47:42we'll commit to one thing.
47:44But then we'll reject a bunch of other things.
47:46So, there's this phenomena happening right now, where, uh, you have these large
47:51cloud providers that offer these services.
47:53The services aren't like, The best, most wonderful things to use.
47:58There's a bunch of companies that'll like, make a copy of just that one
48:01service, but do it like 10 times better.
48:04It's often really compelling, and like you, I can see why people are tempted
48:08to adopt every single one of these, and people end up with a stack where it's
48:11like, It's my application and sitting on top of like 10 different other vendors.
48:17And these 10 vendors are also startups, you know, like it's unclear if they're
48:21going to be around for a while.
48:22So for us, we like as tempting as it is.
48:25And some of it has nice as some of these offerings are like, we never use those.
48:28We just stick to the most lowest level primitives that we can be sure are
48:32going to be around for a long time.
48:34And we'll commit to those.
48:35Like, we're going to accept the fact that if something
48:37happens to them, we're screwed.
48:39More likely we're going to die before they do.
48:40So that makes sense, but like, you know, we won't, we won't apply that everywhere.
48:44So again, it just comes down to like having the right judgment
Updating a local-first app
48:50That makes a lot of sense.
48:52So you mentioned in terms of the deployment cycle, also the update cycle
48:56of your application, and now in the.
48:59local-first way, there is, uh, primarily you need to think about how do I
49:03update the local-first app itself?
49:06So some certain things are easy to deploy, like a, a new component
49:10version of your UI that's, that's easy.
49:13But now that also all of your data lives in the client, the schema of your
49:18data or like the shape of your data is possibly also going to evolve over time.
49:22And there's different ways to deal with that.
49:24So I'm curious how you've handled that.
49:26as well as possibly also the same problem applied to your cloud component.
49:31Yeah.
49:31So in terms of the data locally, we've never done anything sophisticated here.
49:35We've always just blown it all away.
49:36If we have to do some kind of severe breaking change, we will just update like
49:41the big version number and the app will erase everything locally and re sync.
49:46It's not a huge deal.
49:47It's never like massive amount of data.
49:49I think I can see a world where this is, and already it's actually not
49:53too different than changing your back end database schema because
49:56you have similar issues, right?
49:57Like you want to make backwards compatible changes as much as you can because
50:01you don't want to have to like force changes in your application code and
50:03force deployments of those together.
50:05So similarly, most of the time you can do something backwards compatible.
50:09If you totally mess something up, which obviously happens sometimes,
50:11yeah, we just blow it away.
50:13We haven't really found the need to do anything more sophisticated
50:15in what we have, like.
50:17Migration scripts that run locally or anything.
50:19I can see how that's a case for if you're like running, I guess, if it's like end
50:23to end encrypted or something where you can't really do that and the true state of
50:27the data is what's on the person's device.
50:30I can see how you have to like think about that a little bit more.
50:32I think it kind of reminds me of WhatsApp a little bit because like with
50:34WhatsApp, it feels like you're like shuffling your data across your devices.
50:37You get a new device, you like Move the data from one to another.
50:41So I imagine they deal with things like this, but yeah, personally don't
50:44have a ton of experience with that.
50:46Yeah, I mean WhatsApp is also one of the OG local-first apps that
50:51really like followed this pattern out of necessity that defined
50:55why WhatsApp is so attractive.
50:57But I think the, the trade off that you've landed on, I think makes a lot of sense.
51:01It's very pragmatic and given that you're in this hybrid mode of like some parts of
51:06your app are cloud oriented, some parts of your app are local-first, now you can
51:11also reap the benefits of the best of both worlds that allows you to move quickly.
51:16I think if at some point you want to move further on the local-first side.
51:19Spectrum, then I think maybe you can't quite afford just
51:23blowing all the local data away.
51:24I'm kind of exploring some patterns in that regard where I'm kind of keeping
51:29two versions of the data around locally.
51:32One version that is more of like an event log.
51:35And one that is more of like a typical app database.
51:39And the app database is just a projection on aggregate from the event log.
51:44So I also get the benefits and luxury of, in the case of a schema migration,
51:49I can just blow away the app DB.
51:51But instead of talking to the server, I can just replay it locally.
51:55Sometimes takes a little bit of time, but, uh, you get a lot of different
51:58options here that you can choose depending on your requirements and how much time
52:03you can afford to put some effort into.
52:06Yeah, yeah, that makes sense.
52:07And what's interesting is this feels very different, but it just kind of
52:11echoes the same things you do with like a database in the back end.
52:15It's ultimately the same thing.
52:16It just happens to be that the node of the database is running.
52:20In someone's machine, so you end up with like almost all
52:22the same scenarios and options.
New challenges with local-first
52:25Did you run into any situation where you feel like, okay, this was really
52:30easier in the way how you've built software in the past that's now
52:34like either currently harder with local-first or like just categorically
52:39inherently harder with local-first?
52:42Well, it's really that one scenario I talked about before where
52:45you do want to block the user.
52:46Since the default is inverted, whenever, like you never, you never think like
52:51holding the user up until the backend verifies something has happened.
52:5699 percent of developers would never think about that as complicated.
52:58It's like, obviously, that's like how everything works.
53:01But when you invert the default, that becomes a little bit more challenging
53:04and Yeah, we just have to come up with, like, certain patterns around, like, if
53:08you do an action, and a server rejects the action, the natural s thing that'll happen
53:13is your state locally will revert to the state it was at before you did the action.
53:18But that state has no record of you trying to do the action, so
53:21the UI won't have like any error or like information about this.
53:25So, doing an action where there was an error on the backend and preserving
53:28that error, it just ends up being more steps than it would be otherwise.
53:34But again, like we talked about, like this is a minority of cases, so it doesn't come
53:37up, but it's just a funny thing where.
53:39Something so straightforward in the traditional situation is like
53:43so weirdly complicated in this.
53:46So that's one thing that comes up.
53:47I think the second thing that comes up is Kind of going back to this thing about
53:50like the doing migrations of data locally or the schema changes, there's always
53:55a chance, and it's happened more when I was earlier on in doing this stuff.
53:59So I think it was just me, like, not doing stuff well, or like not having
54:03the right approach to certain things.
54:04But, um, Sometimes you would just end up with, like, data that was bad and
54:09messing up the user's state locally.
54:12And with any other app, hitting refresh means, start over, you're, like, rebooting
54:17your computer, you're, like, back to, back to ground, like, back to zero.
54:21But with local-first, you might hit refresh and the local data is still there.
54:24That's causing the bug, preventing, like, you know, the fix from being applied.
54:28So, just like the, you lose the ease of, like, wiping everything
54:32and there's no, like, built in user.
54:34Habits around like, oh, like, let me try clearing my index
54:38DB and my browser, right?
54:39That's like not a thing that anyone thinks about.
54:41So just like guarding those things so you never end up in a
54:43state where it's unrecoverable.
54:46I think that's, that's for good.
54:47Again, it's usually handled on a lower level, so you're not
54:49dealing with this constantly, but.
54:51It is a technical possibility.
54:53Yeah, I like that, uh, that observation a lot.
54:56This is also something I'm currently thinking a lot about.
54:59How can I make that easier through LiveStore?
55:01Since I also, as working both on LiveStore and Overtone, I do discover
55:07those behaviors, whether it's like still me as a developer driving the
55:11user experience where it didn't pop open the console and like throw away, like
55:16all the, the locally persisted data.
55:19But I can't expect an app user to do the same thing.
55:22So I need to build like some sort of, um, guards or some sort of detection
55:26of like, Hey, it seems like the app is in sort of like a really tough spot.
55:31What should we do about this?
55:33Should we try to just like delete a little bit of stuff
55:36that might cause the blockage?
55:39Or what should we do about that?
55:40And so where, where I'm currently at is I think a mixture of user experience
55:45affordances, as well as technical detections, whether something is
55:48wrong, I think transactions can help with that in regards to the technical
55:53abilities, but then in terms of the user experience, similar to like a
55:58React error boundary that you have to detect whether something has gone wrong.
56:02I want to have a similar pattern that allows you to, you know, Click a button
56:07that wipe everything, but it before it does wipe everything, download
56:12a snapshot of your full database that in case something catastrophic
56:16happens, you can, you still have that.
56:18You can hand that to an app developer and you can also later re import
56:22your app state from there so that you can go back where you've
56:26left off in case you wiped it.
56:28So those are like some, some primitives and some, some patterns I'm exploring
56:32right now, but I'm, I'm excited to see what other figures out.
56:36Yeah, that makes sense.
56:37It's also great that you're like, building an actual thing with the tool.
56:43There's just like, no better way to like, really understand
56:46what problems you need to solve.
56:48With SST, like, our console is built with SST.
56:52So, any change we make comes from problems we discover.
56:56The actual product that we're building.
56:57That's why it's so fun to work on like, developer tools, because you are the user.
57:02So you're never like, how do I get in the mind of a user?
57:05Like, that's, that problem isn't there.
57:07Like, you are the user.
57:08It's very easy to figure out what problems there are, um, and discover that.
57:11You kind of skip that whole, like, discovery process that
57:14usually needs to happen.
57:16So if you have someone who's currently like, by default, building
57:20a new app with something like Next.
57:22js or Ruby on Rails, and they, they hear about your story and now they're like
57:27curious about local-first, but they're not quite sure where to get started.
57:31Do you have some tactical suggestions for them?
57:34And also in terms of mindset, what do they need to.
57:39switch in their brain, uh, that they're successful and can hit the ground
57:43running in a local-first mindset.
Advice for builders
57:46Yeah.
57:47You know, it's, I don't think I've really thought about like, what's
57:50the right onboarding path for people doing this type of thing.
57:54I'm like, I know the tools that I use, like I said, we're, we're, we've
57:57centered around Replicache at this point, but you know, local-first website
58:00obviously has a ton of other options.
58:03And there's a spectrum of like what you care about and like how
58:05easy it is and how incremental you can add it and things like that.
58:08But the mindset I think really is, it really has nothing to do with local-first.
58:12And I think it's a good mindset for everyone.
58:14I feel like there has been this shift away from like caring about UX and
58:19almost, I feel like there's like a weird proudness to like not caring about UX,
58:22which I think is fundamentally wrong.
58:24And what I mean by that is.
58:26There's a whole meme of like, Oh, if you did this, you shipped too late.
58:29Or like people are proud of like shipping bad stuff.
58:32Cause they're signaling that like, I'm just someone that
58:35like tries to get stuff done.
58:37I'm not like wasting time on stupid stuff, which the Linear people had a great write
58:43up about this and it's this whole concept around the idea of an MVP is stupid and
58:48it's been stupid for a while, but for some reason, people haven't realized this.
58:52I definitely will acknowledge maybe back when I was starting out, like
58:55in the startup world, like, I guess it's been like 10 or 11 years, things
58:59were definitely different back then where there wasn't a lot of software.
59:02So anything was better than nothing.
59:05So you could really ship something pretty quick and like get validation and move on.
59:09It's like that whole like mindset kind of made sense back then.
59:12But it hasn't been that way in a long time.
59:14So many people ship like something they built in a week and they're
59:17like, Oh, it didn't work.
59:18Let me move on to the next thing.
59:19To be honest, nothing good can really be shipped that fast.
59:23It's just not possible.
59:25Uh, and you really need to have a strong sense of here's a problem I'm solving.
59:30I have good taste around it.
59:31I'm going to put in a lot of effort and make a really great experience.
59:36And.
59:37Whether or not my idea is going to work, you can't know that
59:41until you've hit that bar.
59:43And as a Linear people wrote up a whole thing about this on like, we're so
59:47obsessed with these like little tiny MVPs.
59:50And that's like the weird default that we're all like kind of
59:52proud to say that we follow that.
59:54Um, and the mindset shift is with local-first, it's getting easier all
59:59the time, but it's going to be a lot harder than a lot of things that you've
1:00:03done before because you have so much time to focus on these little details.
1:00:08And you really have to focus on details.
1:00:09You have to enjoy Letting them and caring about them and making that
1:00:14feel good because that's what that's where the bar is now, whether people
1:00:17realize it or not, the fact is Linear, Linear exists now that it exists.
1:00:23How can you possibly ship anything not at that level?
1:00:26Right?
1:00:26How, like, sure, in the short term, I'm sure you can, but the long term,
1:00:29obviously that becomes a new bar.
1:00:32So, for me, the mindset shift is like, there is a new bar go use products that
1:00:36are like this, like, Linear is one, like, superhuman is like a smaller example.
1:00:40of stuff that's kind of gotten bigger.
1:00:42That is the bar, and you have to accept that that is a bar.
1:00:45And if you really accept that, then you'll be motivated to like
1:00:48go and figure out all this stuff.
1:00:50Yeah, it's quite different from where I think the mindset is currently.
1:00:54I think you've very succinctly Summarized my last two and a
1:00:58half years working on Overtone.
1:01:00I'm exactly inspired by that high bar.
1:01:03Sometimes I might even raise it a bit higher just for, for the challenge, but
1:01:08it's so fun to see like all of those details just compounding and, and I
1:01:13like much smoother product experience.
1:01:15And, uh, yeah, I love the the blog posts that you've pointed
1:01:19out from the, the Linear blog.
1:01:21And I think the only exception really to where the bar needs to be higher is
1:01:25like for just categorically new things.
1:01:28Maybe an exception here is like AI products, uh, like AI products.
1:01:32There is no, no prior version to that.
1:01:34So maybe it is really speed that, that matters most, but I think
1:01:38for every software that replaces something that was there before.
1:01:43I think it's, you have to really, really care about craft.
1:01:46Um, Arc is another example as like to really innovate on a browser.
1:01:52Like the browser is still the same, what it is before, but now it's
1:01:55like all the compound effect of all of like getting the details right.
1:02:00And that really, that really excites me.
1:02:02So thank you so much for that wonderful summary.
1:02:05Yeah.
1:02:05And there's so much opportunity to do this.
1:02:07Like I'm unhappy with so much of the things that I use every day.
Outro
1:02:14Thank you so much.
1:02:15This has been really, really fun.
1:02:17Thank you so much for coming on.
1:02:19Yeah, appreciate having me.
1:02:20I, I, it was good.
1:02:21I actually don't get to get into some of these details.
1:02:24I don't, I've actually never gotten a lot of these details before.
1:02:26So yeah, it was great.
1:02:27Thank you for listening to the localfirst.fm podcast.
1:02:30If you've enjoyed this episode and haven't done so already, please subscribe and
1:02:34leave a review wherever you're listening.
1:02:36Please also tell your friends about it.
1:02:37If you think they could be interested in local-first, if you have feedback,
1:02:41questions or ideas for the podcast, please get in touch via hello at
1:02:45localfirst.fm or use the feedback form on our website, special thanks to Expo and
1:02:50Crab Nebula for supporting this podcast.