Background
Patrik Wassberg, joined us to discuss Krooka Fishing, an app for organizing and running fishing competitions that keeps working even when participants are fishing in remote locations without internet connectivity. We spoke to Patrik about the Krooka stack, why they decided to follow a local-first architecture and what the future holds for them.
App details
* Krooka is still in development, with a release planned for later this year.
† “Krooka” is a Swedish verb / slang for “to hook [a fish]”.
Interview
PowerSync
Why did you decide to follow a local-first architecture for your app?
Patrik
The main reason was offline functionality. The whole reason why we started building this app was because there are issues when you're out fishing in the sea or at a lake deep in the woods: you can have a terrible internet connection. My friends and I have used other apps [that weren’t offline-first] and most of the time we weren't able to upload anything when we were actually fishing.
But also the instant UI — you get changes in milliseconds instead of maybe two or three seconds, and if you have a bad connection, it can be even worse. But apart from that, I also found that in terms of state management, I don't have to handle as much as I do with like Zustand or Redux because since it's so quick, you basically have everything on the phone and it gives you that data in milliseconds so there’s no need for any advanced state management.
I also plan on using [the sync engine] kind of like a content management system, because it gets messages to users really quick through the PowerSync Service, because you can just make an entry into the database and then it syncs to all the users. This could include outages, promos — if you have in-app purchases and stuff like that, or anything you want your users to know of quickly.
PowerSync
What was the main thing about PowerSync that stood out to you? Or, put a different way, what would you consider to be the most valuable thing about PowerSync?
Patrik
It’s really easy to use your Supabase example and try it out. It felt like it checked all the criteria that I had, so after playing around a bit, I started planning the actual application. I think you guys launched around the same week that I started looking — maybe in October or November [of 2023] so it was a lucky match!
PowerSync
Some of the feedback that we've gotten from other developers that are using PowerSync has been similar: they’re looking for reliability, robustness, stability. So that is kind of a theme.
Another piece of feedback that we’ve heard often is around PowerSync’s non-invasive architecture: you can basically view it as middleware between your Postgres backend database and your app and you can also take it out again. You don't have to modify your backend or your Postgres database extensively as you have to with some of these other tools. Developer experience or kind of just ease of getting started is also feedback that we've heard developers talk about. Developer control or customizability: for example, you can define how writes get applied to your database, so there's a level of customizability there. So those are some examples of feedback that we've gotten. Do any of those resonate with you as well as far as things that you found valuable in PowerSync?
Patrik
Yeah I would say the non-invasive part resonates: it feels like I could very easily disconnect PowerSync and just start using a normal API again. It’s nice because you don’t have to rewrite anything if you for some reason want to stop using it or move to something else.
PowerSync
How about ease of getting started? It’s really easy if you start with Supabase but maybe a bit more complicated if you're not using Supabase. Was there a learning curve getting started with PowerSync?
Patrik
Yeah I think there was. I have a lot of complex queries — a lot of joins and stuff like that — so when I started I basically thought I could write any kind of SQL in [Sync Rules] so that it was a bit of a learning curve. But I guess it's also on users who are maybe not really reading the documentation properly, maybe just going off the examples and then trying to customize them to our needs without actually reading what we can do. But I got some help from [the PowerSync team] and after that I kind of understood how I could solve some of the more complex stuff.
PowerSync
We’re obviously big believers in local-first or offline-first architecture because it has a lot of benefits. You've touched on several of them, simplified state management, low latency UI because of the speed of queries, offline mode, real-time, those kinds of things.
In the past, a lot of people didn't implement a local-first or offline-first architecture because it was difficult to implement. But what we want to help do is to make local-first so easy to implement that people just go straight to a local-first architecture for a new application instead of the traditional cloud-first approach. In light of that, are there any ideas that come to mind that could be useful for us to consider?
Patrik
Now that I’ve been working with PowerSync for some months, I don't think it's that harder than a traditional API-only solution. I would say that it's easier: I have to write less API routes and endpoints for fetch and stuff like that. The big hurdle is if you’re not using Supabase, yeah — writing your own API and connecting that stuff. I can't really think of anything else that would make it easier.
PowerSync
Thanks. Can we talk about your web app? What stack are you using for that?
Patrik
It’s going to be React with Vite. I was doing Next.js first but I didn’t like the developer experience and I don’t need SSR for the web app. Next.js is a good framework, just not for me.
PowerSync
Will the web app be using your own APIs?
Patrik
Yes, it’s going to use our own APIs and PowerSync.
PowerSync
Great. So you'd actually have all the web app’s user data in SQLite, in the browser and have essentially the same architecture as mobile, just in a browser.
Patrik
Yes
PowerSync
On the API: do you have a single fat endpoint or a bunch of endpoints?
Patrik
Oh, I have a bunch of endpoints. Like 90% of my work is frontend and then I have a friend who does some of the backend stuff.
PowerSync
So, on the client, your upload data implementation is quite a few lines of code checking for various scenarios and writing to various endpoints based on whatever is happening in the upload queue. Is that correct?
Patrik
Yeah. And I also have some wrapper functions for stuff like parsing JSON and stuff like that.
PowerSync
And are you using transactions or just the regular CRUD batch?
Patrik
Transactions, yeah.
PowerSync
And what was the main restriction on Supabase that sent you down the route of building your own API with Go?
Patrik
Yeah, a lot of different things… We have complex queries and different tables that need to be [updated]. Like if I insert into one table, I need to insert a row in one or two other tables [as well]. I was using Postgres functions but it got so messy: it was hard to write — at least for me. It was just easier to create our own backend API, and handle it that way.
PowerSync
Okay, and Supabase Edge Functions weren't really sufficient for doing those kinds of things?
Patrik
Yea I played around with it a bit, but I didn’t like the developer experience, you could say. I felt it was just easier to have my own API and if we want to change stuff in the future it feels like we have way more control over our data and how things work. We are actually still using Supabase for Edge Functions for push notifications and for authentication — just because of time constraints. Although I don’t know if we will have the time to migrate away anytime soon.
PowerSync
Okay, understood. Thank you so much for joining us Patrik, we really appreciate your time!