skip to content
Podcast cover art for When to Declare Technical Bankruptcy?
Podcast

When to Declare Technical Bankruptcy?

Christopher Burns details how he rebuilt his startup Ever Fund using Redwood JS, transitioning from a fragile multi-service MVP to a streamlined monolith.

Open .md

Episode Description

Christopher Burns details how he rebuilt his startup Ever Fund using Redwood JS, transitioning from a fragile multi-service MVP to a streamlined monolith.

Episode Summary

In this episode, Christopher Burns walks through the technical journey of rebuilding his UK-based donation platform, Ever Fund, from a fragile MVP built on Hapi, Prisma 1, MongoDB, and Gatsby to a far more stable stack centered on Redwood JS, Next.js, and Postgres. He explains how the original architecture—spread across multiple Docker containers, separate repos, and hosted services—became unmanageable when customers requested features like updating donation links and filtering data through a dashboard. The breaking point led to what co-host Anthony Campolo calls "technical bankruptcy," prompting a complete rebuild. Burns credits Redwood's scaffolding, auth library, SDL generation, and opinionated patterns with providing the "technical wealth" needed to ship a production app as a solo developer in just four months. The conversation also covers why Next.js was chosen specifically for donation links (incremental static regeneration solved the Gatsby rebuild problem), how Stripe Connect Custom drove architectural complexity, the challenges of webhooks across Vercel and Stripe, and ongoing puzzles like wildcard SSL proxying for custom customer domains. The hosts tease upcoming episodes on third-party service integration and a roundtable with representatives from Redwood, Blitz, and Bison.

Chapters

00:00:00 - Introduction and the "Built Redwood Before Redwood" Mantra

Christopher opens with the central theme of his recent Redwood JS meetup talk: that many developers end up independently solving the same problems that full-stack frameworks like Redwood now handle out of the box. He shares that even Redwood community member David Theisen resonated with this idea after watching the presentation.

The hosts introduce themselves and their Twitter handles, encourage listeners to follow the FSJam account for updates on Redwood, Blitz, and Bison, and set up the episode's focus on Christopher's startup rebuild. Anthony notes that seeing Christopher's architectural diagrams from the talk made earlier podcast discussions click into place, particularly the goal of collapsing everything into a single "majestic monolith."

00:03:18 - The Original MVP: Hapi, Prisma 1, and Docker on DigitalOcean

Christopher explains why he chose Hapi over Express (TypeScript support recommendations at the time) and walks through the original backend: MongoDB Atlas, Prisma 1, and Hapi, all running in separate Docker containers on DigitalOcean with minimal security between them. Anthony points out that this setup was essentially a microservice architecture, contrasting it with the modern approach of using Prisma as a straightforward ORM.

The discussion touches on how Prisma 1 was built in Scala and required Docker, how an initial attempt to host on AWS Fargate proved too expensive, and how GraphQL Nexus sat on top of Apollo Yoga on top of Hapi—frameworks stacked on frameworks. This complexity was the key motivation for Christopher's eventual move to Redwood, whose API layer he rates nine out of ten, with the only missing feature being automatic SDL scaffolding for external services like Stripe.

00:08:56 - Stripe Complexity, OneGraph, and Shared Tooling

The conversation shifts to why Ever Fund's GraphQL graph became so large that it couldn't fit on lambdas, largely due to Stripe Connect Custom's extensive API surface. Anthony brings up OneGraph as a potential abstraction layer, but Christopher explains that Ever Fund needed direct access to Stripe JS for the custom parameters required by Connect Custom accounts.

They also discuss Brian Douglas's use of OneGraph for GitHub's GraphQL API, the idea of integrating OneGraph's query-builder into Redwood's GraphQL playground, and the broader opportunity for Redwood, Blitz, and Bison to share generator tooling rather than each building bespoke solutions. Christopher reiterates his talk's core message: all three frameworks are independently making the same breakthroughs on roughly the same timeline.

00:13:11 - Technical Debt, Gatsby's Rebuild Problem, and the Breaking Point

Christopher describes how the original Gatsby-based donation links worked fine at small scale but became untenable once customers had hundreds or thousands of links—any single text change triggered a full site rebuild. The dashboard, also in Gatsby, communicated with Hapi through Apollo and relied on hand-rolled authentication with minimal team support.

The tipping point came about five months prior when a customer requested what should have been a straightforward feature—programmatic link updates and donation filtering—but the existing codebase couldn't support it. Anthony frames this as "technical bankruptcy," and Christopher agrees, noting that the MVP had proven the business concept and was generating revenue, but the accumulated technical debt made further development impossible without a ground-up rewrite.

00:19:39 - Patterns, Technical Wealth, and the Redwood Rebuild

Christopher emphasizes that the difficulty wasn't the features themselves but the lack of uniform patterns across the codebase—every piece was coded differently with ad hoc solutions. Anthony connects this to ETL challenges and the reality that even experienced developers learn by referencing tutorials and demo repos. The conversation turns to how Redwood provides "technical wealth" through scaffolding, SDL generation, and its auth package.

Christopher shares a concrete example: implementing multi-team support was nearly impossible in the old stack but became trivial in Redwood using user context and role-based hooks. He rebuilt Ever Fund in four months as a solo developer, a feat that astonished attendees at the meetup, though he's candid about the personal cost in family time and long nights that made it possible.

00:25:31 - Database Choices, Postgres, and the New Hosting Setup

The hosts discuss how the new stack consolidates hosting on DigitalOcean, with a managed Postgres database replacing the old MongoDB Atlas setup that had been expensive for London deployments. Christopher admits his reason for choosing Postgres is simply that Prisma 2 supports it well, while Anthony makes the case that Postgres is widely regarded as the best general-purpose SQL database by serious DBAs.

They briefly touch on Fauna as an interesting alternative worth experimenting with, then Christopher outlines the additional services running alongside the Redwood API on DigitalOcean: a separate Express server for file uploads (needed to pass verification documents to Stripe without exposing secret keys on the client), and a standalone webhooks handler that was necessitated by unresolved issues between Redwood, Vercel, and Stripe each pointing fingers at one another.

Christopher explains why Ever Fund uses two separate front ends: a Redwood Web dashboard (benefiting from auth, private routes, and scaffolding) and a Next.js app for donation links (leveraging incremental static regeneration to avoid full rebuilds). He argues that building user interfaces consumes roughly 70% of development effort compared to 30% on the API, and that choosing the right tool per client is essential.

The conversation detours into state management and caching—Christopher uses standard React context in Redwood and a library called Pullstate in Next.js—before returning to the architectural picture: nearly everything lives on DigitalOcean, with only the donation links on Vercel. Future plans include moving the Next.js client into the DigitalOcean monolith once wildcard SSL proxying for custom customer domains is solved.

00:39:50 - Third-Party Services, Search, and Cool Extras

Christopher rounds out the tech stack by listing the third-party services integrated into Ever Fund: Magic Links for passwordless auth, Postmark for transactional email, and Stripe for payments. He also highlights features that Redwood's boilerplate made easy to add in the rebuild, including team management, detailed error handling via AppSignal, user activity logs that track every service call, and role-based access control.

Anthony mentions the CASL authorization library and suggests a dedicated episode on authentication versus authorization. Christopher reveals the "drop the mic" moment from his talk—that a single developer built the entire platform in four months—and notes that even Tom Preston-Werner reacted with surprise. They agree the topic deserves further exploration around third-party service integration.

00:47:39 - Ops, Hosting Independence, Latency, and Closing Remarks

The hosts discuss the reality that launching is only the beginning: Ever Fund is still in soft launch without every required feature, and operational concerns like 2 a.m. crashes are real. Christopher notes the advantage of self-hosting on DigitalOcean—when AWS's us-east-1 went down and took parts of Netlify with it, his infrastructure stayed up. Anthony clarifies that Netlify's CDN is globally distributed but its serverless functions on the free tier do depend heavily on us-east-1.

Christopher closes with a light complaint about one-second latency to a US-West-2 provider from Brighton, UK, marveling at how fast data actually travels halfway around the world. The hosts remind listeners of their Twitter handles, tease an upcoming episode with Brandon from Blitz, and preview a holiday roundtable featuring representatives from Redwood, Bison, and Blitz discussing the future of JavaScript in 2021.

Transcript

00:00:00 - Christopher Burns

That's the real mantra to my talk: I built Redwood before Redwood. When I got a moment to speak to David Theisen from Redwood, he literally said to me, I understood your talk and I felt the exact same thing. I built Redwood before Redwood. It's like we're all building Redwood before Redwood.

Welcome back to the podcast, episode five. This week we're going to talk about how I built my new startup on top of Redwood, the transition from our previous MVP technology, and a lot of other subjects.

Before we go into the main topics, I just want to highlight two things. A lot of people have not put our faces to our voices, so you can follow me on Twitter, Burned Chris, and Anthony, AJC Webdev.

00:01:08 - Anthony Campolo

It's for my initials, Anthony, my middle name, and Campolo. The J stands for Joseph.

00:01:17 - Christopher Burns

I was going to say Joseph. That's literally the first one that came to my head. Joseph.

00:01:21 - Anthony Campolo

Very biblical.

00:01:22 - Christopher Burns

Yeah. So you can find me at Burned Chris on Twitter and Anthony at AJC Webdev. You can also follow our Twitter account at FSJamOrg. We are always posting updates about upcoming episodes and what else is happening around Redwood, Blitz, and Bison, so it's always a great follow. So let's jump in.

00:01:46 - Anthony Campolo

Yeah, it's going to be interesting to talk about this stuff now that you've done a full presentation about it. We've mentioned it throughout many of our episodes, especially episode zero and episode one. You told your whole history of your stack and how you built it, and then how we've transitioned that to Redwood, and then how you also thought about combining Redwood and Next into this kind of hybrid.

So when I was able to see your slides and your architectural diagrams, which we'll link to in the show notes, I got it immediately. I was like, oh, this is the stuff he's been talking about. A lot of it clicked together. I thought you did a really good job of explaining the difference between the two architectures and how you've been able to simplify your stack. I also think it's interesting how you think you can simplify your stack even further. You're trying to get everything into one giant box.

00:02:37 - Christopher Burns

One giant monolith.

00:02:39 - Anthony Campolo

The majestic monolith.

00:02:40 - Christopher Burns

The majestic monolith. As Anthony noted, I recently did a presentation at the latest Redwood JS meetup. Dom over at Redwood had the recording, edited it down for me, and I've posted it on YouTube, so a link will be in the description if you want to watch my talk. There will also be the slides if you just want to read them.

It was a very tight slice of what we've been able to achieve with Ever Fund and Redwood and Next.js, and I'm sure this will be the in-depth version of the good, the bad, and the ugly on things that I didn't cover on the rosy path to Redwood. So where should we start?

00:03:18 - Anthony Campolo

Where should we start? I thought it was interesting. The one thing we didn't talk about the first time we talked about this was that you used Hapi. Why did you use Hapi instead of something like Express?

00:03:26 - Christopher Burns

I was still newish. I wanted to use TypeScript. A lot of people were like, yeah, Hapi is really good for TypeScript. So I was like, cool, I'll use Hapi. I never really looked at Express. I knew what Express was, but I just thought it was really basic, when it can be pretty good as well. Also, what got deprecated not long ago? Hapi did. A lot of the technologies I used in version one are now deprecated. The crazy thing about that was that all of this was only worked on a year ago.

00:03:56 - Anthony Campolo

Well, don't they have a new team now? They deprecated it, but the idea is that Hapi now has a second life. That's how I understood it when it was announced.

00:04:04 - Christopher Burns

Are they working on a new Hapi 2 or something? I'm not quite sure off the top of my head.

00:04:09 - Anthony Campolo

I would guess so, but it was like an announcement of, we have a whole new team, we're working on this now. We'll link to that.

00:04:14 - Christopher Burns

Let's just give an overview for the people that are just listening to it. So if you're in your car or you're just listening as you go, we're going to explain the majestic MVP of Ever Fund.

Where to start? We'll start with the backend, the ugly side, as I may say. It had three elements: MongoDB Atlas hosted Mongo database, Prisma 1, and Hapi as the server.

00:04:46 - Anthony Campolo

So is Prisma and Hapi both hosted on a server on DigitalOcean?

00:04:50 - Christopher Burns

Yes, they were both dockerized on DigitalOcean, and I still, to this day, truly do not understand how Docker works fully and how to create images.

00:04:59 - Anthony Campolo

So if they were both dockerized, they should both be their own box talking to each other, instead of being in one box.

00:05:06 - Christopher Burns

Yes, they were in different boxes. They just didn't have much security around them, so they were very easy to talk to each other.

00:05:12 - Anthony Campolo

Interesting. And then you have GraphQL pointing between the two of them, because that's how they were speaking to each other. This is what we talked about, the whole thing is GraphQL or not, and does it use Nexus or not. Go back and listen to the initial episode to kind of get that background there.

But I think it's interesting that you still end up with a database and a server and a front end, so you end up with kind of like three pieces here. I guess it would have been four pieces because Hapi and Prisma are both their own server. I think what a lot of people ended up with when they had Prisma was almost like a microservice architecture. And now we've moved to more of a monolith and using Prisma more like an ORM kind of tool, which they have finally caved. If you go to their home page, they're prominently called an ORM now.

00:05:58 - Christopher Burns

Is there a next generation ORM, though?

00:06:00 - Anthony Campolo

Next generation ORM? Sure. Why not? You can be any kind of ORM you want to be.

00:06:05 - Christopher Burns

Prisma, the future of ORMs. If you didn't know, the first version of Prisma was developed in Russia, I want to say off the top of my head.

00:06:16 - Anthony Campolo

It was Scala. Now it's in Rust.

00:06:18 - Christopher Burns

Scala. That's it. It was Scala and it had to be dockerized. So you had to run it in a Docker container. The first thing we looked at was let's host it all on AWS and Fargate. That is expensive. So then we went down the, we'll just host it all ourselves on DigitalOcean. That was a joy.

As you can tell, the Hapi server was built with multiple technologies that were really not fun and pretty, but they worked and that's why we kept on moving forward with it, such as Prisma. Is it Prisma Nexus or GraphQL Nexus?

00:06:54 - Anthony Campolo

Yeah, it's called GraphQL Nexus. They don't put the Prisma name in it because it's like an open source project that's sponsored by Prisma.

00:07:02 - Christopher Burns

It was like the old one. Pretty sure they deprecated that, then built a new version of it.

00:07:07 - Anthony Campolo

They had a framework built around the library. They've kind of gotten rid of the framework, and now they're just investing more heavily in the library, I think, is kind of the situation right now.

00:07:16 - Christopher Burns

The main point of Nexus, sorry, the Prisma GraphQL tooling, was that it helped you create the CRUD operations really fast, but also the mapping of the GraphQL to the client through Apollo.

So you had Hapi as the base layer, but it wasn't even the base layer. You had Docker as the base layer, with Hapi above it, with, I think, GraphQL Yoga above that, with Nexus above that, communicating up and down all the way to a server and back. A lot of moving parts and a lot of services running and frameworks built on top of frameworks.

This is what really moved me towards Redwood JS in the first place because, hands down, I really like Redwood. The API is near perfect for myself. The perfection of the API is top level, nine out of ten. The one golden feature I wish that I could add is automatic scaffolding of SDLs for external services like Stripe, but obviously at this point you can only scaffold and generate your SDL.

00:08:27 - Anthony Campolo

That's the kind of thing where it's like you can have that if you build it yourself, and then everyone else can have it too.

00:08:32 - Christopher Burns

I've got Stripe as an SDL, so.

00:08:34 - Anthony Campolo

That's what I'm saying, because a decent amount of people use Stripe who are using it for payment, but not everyone who's using Redwood is using it for payment. So that's still kind of a specialized use case.

00:08:42 - Christopher Burns

And the Stripe graph is massive. And I think that was the core reason our functions never fitted on lambdas, because our graph was just massive because of all the extra functionality of Stripe.

00:08:56 - Anthony Campolo

Do you know anything about OneGraph?

00:08:58 - Christopher Burns

OneGraph? Interesting. Yeah, I like OneGraph. But the problem is that, for us personally, we're using Stripe Connect Custom, so we wanted more control over the connections. So the point of OneGraph, what you could do, is say I just want to communicate straight with Stripe. And you could do that through OneGraph. So OneGraph would be your communication layer but also the SDK library. So obviously the OneGraph is then communicating with Stripe JS in the background that you never see. But for us, we wanted to see the Stripe JS. We wanted to add the extra parameters needed for Stripe Connect Custom.

00:09:37 - Anthony Campolo

Now that's interesting. The reason I asked is OneGraph is being used by Brian Douglas for his project called Open Sauced. He uses it for GitHub's GraphQL API because I would imagine, in terms of complexity of APIs, GitHub's GraphQL API is up there with something like Stripe.

00:09:53 - Christopher Burns

GitHub's API is probably, I would say, about a third of Stripe, because the problem with Stripe is you have a lot of different services now, and they keep on adding more services.

00:10:04 - Anthony Campolo

So it's not just Stripe. You're hooking into other things that aren't Stripe also, is what you're saying.

00:10:09 - Christopher Burns

Yeah.

00:10:09 - Anthony Campolo

Gotcha. Because this is the whole point of OneGraph, as I understand it, to normalize your graph across everything.

00:10:16 - Christopher Burns

Well, yes, that as well. But also you can abstract away your API if you require your backend. You could say, I'm going to have a Next.js front end that just straight communicates with OneGraph and never need an actual API or a service running.

00:10:31 - Anthony Campolo

And that's probably, if Blitz would bring in something like GraphQL, that's how they would probably do it.

00:10:36 - Christopher Burns

Probably. I think OneGraph is awesome. One of the things about OneGraph that I do think is really awesome, and that I've been trying to persuade the Redwood team to integrate, is to move away from the GraphQL playground as the default client to GraphQL.

The main reason why is not because of dark mode as most people prefer, but because OneGraph made a plugin for GraphQL that basically builds your query. When you select all the things you want on the left, it then will build it into the correct hook structure. Gatsby has it added to their GraphQL. So, for example, you literally click all the things you want. It gives you code export of, this is the code you need to just paste into your JavaScript file and it will work.

What I imagine, if Redwood adopted it, they would say, okay, click these options in the graphical user interface, and then you can code export a cell. That obviously requires more of a user interface than a CLI, but then it would give more options to that client as well.

00:11:46 - Anthony Campolo

This is what you talked about actually in the roundtable with Peter, Brandon, and Chris. You guys talked about creating some sort of universal generator tool that could be shared between the three frameworks. This would apply more so to Redwood and Bison being heavier into GraphQL, the same kind of idea of having a really powerful generator, because we're all building our own bespoke generators right now.

00:12:06 - Christopher Burns

And that's the biggest thing. There is obviously so much room, and all three of these frameworks are doing the same work and not necessarily sharing. It's almost like, as I said in my Redwood talk, we're all building the same things. So why don't we just let one person do it for us? That's the real mantra to my talk.

I built Redwood before Redwood. When I got a moment to speak to David Theisen from Redwood, he literally said to me, I understood your talk and I felt the exact same thing. I built Redwood before Redwood. It's like we're all building Redwood before Redwood.

A lot of these integrations are super non-trivial. You'd think they would be very straightforward, just add Storybook, just add Jest, just add more workers. Even adding data to your seed because you've got a live application and you want to test it, are you going to use fake data? Are you going to use real data? I know Peter from the Redwood team is working on a product that does something along these lines.

00:13:11 - Christopher Burns

Hopefully some of them will be really helpful to help expand Redwood and even Bison and Blitz. I remember when I last spoke to Chris Ball, who will be a guest in January, he was working on a breakthrough in this area.

It really feels all of these frameworks are making breakthroughs, but it's almost the same breakthrough in the same month because they all solved the same problem and they go, what's the next problem? And then this is the next one, and they're figuring out their own ways to those solutions. That's really fun.

To bring it back to the point of Ever Fund and our old technology stack, the Hapi server, the Prisma 1, the server basically fell apart. I went from what I believed was a two out of ten server to a nine out of ten. Redwood is amazing on the server.

On the clients, I decided what technologies have I used? I've used Gatsby a lot. I think this could work in Gatsby. We went down the route of Gatsby. Our dashboard and our donation links were coded in Gatsby.

00:14:40 - Anthony Campolo

So you had two different Gatsby apps. Were they in the same repo?

00:14:44 - Christopher Burns

No, separate repos.

00:14:46 - Anthony Campolo

Okay, so those should also be their own separate boxes. So you've got two boxes here, but really there should be like five boxes here.

00:14:53 - Christopher Burns

Yeah. It was super hard to manage it all. And it got to the point when we said we're working on a new version. We just halted development and support on the original version and kind of put the title, it is as it is, until the new version is out.

Our customers have now started onboarding and taking payments on our new version. Today was the best day for our new version. Our payment platform processed approximately 750 pounds. It's obviously the biggest day since it's been relaunched three or four days ago, but it obviously is showing that what I've built is working and is far more stable. And that makes me really, really happy.

Why did I pick Gatsby? Gatsby is what I knew, and I had this idea in my head. One of our main features of Ever Fund is that we've created this brand new technology that we call donation links. Imagine a short URL service like bit.ly, and then also imagine Stripe. But what happens if every time you generated a bit.ly or a short link, you got a new Stripe checkout? That's the main core of Ever Fund. It's a payment checkout specifically driven for charities and nonprofits in the UK.

00:16:11 - Christopher Burns

So that means we take things into Gift Aid, a tax scheme in the UK. Every donation can be increased by 25%. Real big deal. We allow our donors to cover the costs of the payment, so these things help the charities convert more donations and be more transparent with their donors. The biggest thing is giving them more data.

But back to the point of the links. I'm going to generate 50 links. That's great. I say to Gatsby, build 50 new links. Gatsby goes, okay, I'm going to go away and build 50 new links because we wanted the open graph data. When these links are shared on Facebook or Twitter or Instagram, you would get the nice open graph data.

That was great. In the early days, the prototype worked perfectly. It would create the links as we needed them. Then we started expanding. Can I have 700 links? Can I have 800 links? And you go, okay, yep, it's still fine.

Then the problems really started showing when they started saying, can I change this link? Can I change the text on this donation portal? Can I update the goals? And then you'd go, yep, our system has now 1,000 links activated. One link has changed, so we've now had to rebuild the whole Gatsby website with the 1,000 links. You start seeing the problem of one tiny change now causing a whole platform to be rebuilt. This was the big open question that we didn't know where to go. That was the donation links.

On the other side, we had the dashboard that was also built in Gatsby. It communicated through GraphQL Apollo to Hapi. I can't quite remember off the top of my head if there are specific React hooks for Gatsby or they're just React hooks. A lot of our implementations of things like auth and management of data were using very general libraries. So a lot of this authentication layer had to be done by ourselves. Obviously inexperience took over and we just got by. We had user login sorted, one user per account, no teams or anything like that.

When we decided, look, this current MVP worked. It proved the concept. We started making money on it. We were taking donations for our charities. We onboarded more charities. The problem started growing and growing, and the biggest problem that broke the camel's back was when our donation platform asked for a massive feature. We took a look at our technology stack, started to try to develop that feature, and it broke the camel's back.

00:18:52 - Anthony Campolo

And how long ago was this that this happened?

00:18:54 - Christopher Burns

This was about five months ago. So it broke everything.

00:18:58 - Anthony Campolo

And are you able to say what that feature is? Can you describe it at least generally?

00:19:01 - Christopher Burns

It's a very trivial feature, as I said, with the donation portals: updating them programmatically with Gatsby, and also management of single donations through a dashboard and an API, and filtering them and doing data manipulation on them.

These things sound so straightforward, and I understand that you could be a junior developer right now and think, that sounds really hard, or you could be a senior developer, then go, that sounds easy. The difference is that the pattern is the key. If you don't understand the pattern, you're going to struggle to do it at the end of the day.

00:19:39 - Anthony Campolo

So you're just talking about the ETL type stuff, ETL being extract, transform, load. You have data that's going to come from one place, has to get to another place, and it's going to be in one form, and it has to get there in a different form. And doing that is really complicated.

00:19:53 - Christopher Burns

Exactly. And CRUD, all of these things are really complicated when you're doing it by yourself for the first time. What do you do? You look at tutorials, you look at demo repositories, and you work it out, right?

00:20:09 - Anthony Campolo

I would never do that.

00:20:10 - Christopher Burns

I know you wouldn't. I learn when I code.

00:20:13 - Anthony Campolo

No, I'm totally kidding. That's all I do. That's what everyone does. It's what anyone can do with this stuff.

00:20:18 - Christopher Burns

Exactly. And the problem is, no uniform patterns were being produced. Everything was coded differently, with different hacks and solutions implemented to get it moving.

So then we decided, look, it works. Right now it works. We're so sorry to our customers, but we're going to have to go away and reprogram it. With an MVP, you prove that it works as fast as you can, and then you go, yeah, it's going to be hard. It's kind of like the whole philosophy of you go to a hackathon, you spend all night, and then you come to the presentation, you go, yeah, this is what I built in 24 hours, and a company is like, oh, yeah, I like that. I could do with that in my business. After the fact, the company goes up to the people that built that stuff and they go, so how long would it take you if you built all of that in 24 hours? How long will it take you to build this extra trivial feature?

00:21:12 - Christopher Burns

A month?

00:21:13 - Anthony Campolo

Nah, a year.

00:21:14 - Christopher Burns

A year, you know, because it's built to prove the purpose.

00:21:20 - Anthony Campolo

And this is a great segue into a term that you used that I really would like to hone in on. What you're describing is technical debt, and it sounds like you hit a point of technical debt where you had to declare technical bankruptcy because it got so bad. And what you need is technical wealth.

00:21:40 - Christopher Burns

Exactly. And I didn't come up with this term. The first person that said this term to me was Monarch on episode three of our podcast. He quickly brushed over the term. It sat in my mind, and I quickly said it at our meetup.

The main point to go into is that Redwood adds, by default, so much technical wealth that you would be challenged not to take it. For example, the scaffolding. Our MVP proved as fast as we could. The solution worked. But what we could have done, if we had the technical wealth of Redwood, is build the scaffold as fast as we could, prove that it worked with the scaffold, and then go into depth on the features and the other things faster.

SDL support, the generation, the auth. The auth package is amazing. I would rate it eight out of ten. Amazing.

00:22:43 - Anthony Campolo

Yeah, I give it a nine out of ten.

00:22:44 - Christopher Burns

It's not as good as the API, but I really do like it. Why? Because it makes it so easy to get moving with good practices. For example, with our first version of Ever Fund, if you ask me, okay, add multiple team support, I would go, I don't know where to start. Do I add it on Auth0? Do I add it on our database? I don't know.

But with Redwood, instantly in my head, Redwood gives you a user context. What you need to do is say I'm part of team A in that user context, and then when they save a form, you instantly go, they're part of team A, to obviously limit and give them correct data from only that team. Then you make a nice little user interface that allows them to swap team or create a new team. Now you say I'm part of team B, so then you update the context to now say you're part of team B. That was so trivial in Redwood. When I was doing it by myself, it was the hardest task that I could think of.

00:23:45 - Christopher Burns

And this is why I'm really backing FSJam frameworks, because the amount of technical wealth they give you is incredible. I rebuilt Ever Fund in four months, and most people at the meetup were astonished, from what I understood. But there's a lot of long nights and not spending a lot of time with my family, my partner.

00:24:32 - Anthony Campolo

That's spending time with this podcast.

00:24:34 - Christopher Burns

Not spending time with the podcast. Obviously, you have to weigh things up. I find it always important to say why I did build it in four months. My family, my partner, they took the sacrifices. That's all I can say about that, about building Ever Fund.

00:24:50 - Anthony Campolo

I thought your presentation was super awesome. It really showed what has gone into putting an application like this together and the type of iteration you have to do to get there. I definitely think people should check it out. We're onto your database setup now, which has Prisma and Postgres. What I find interesting is now you have everything hosted on DigitalOcean, so you don't have as much piecemeal stuff hosted in different areas because you're able to have your server and your database both in the same place. Before, you had Mongo and your Hapi server and your Prisma thing all in different areas.

00:25:31 - Christopher Burns

I've said to you, I have no clue what the best database provider is, which one I should pick, why I should pick it. At the time with Prisma 1, everyone spoke to me about MongoDB. You should use MongoDB.

And if you didn't know, MongoDB is really hard to host on someone else's servers. So I used that Atlas product and it got expensive very fast for London deployment. We're not in a free zone in London, so we have to pay. Our database was hosted on Atlas that communicated to our DigitalOcean cluster that spoke between the Docker containers.

With our new version, DigitalOcean manages our database and it's a Postgres database. If you asked me even now why Postgres, my answer, as simple as it is, is Prisma 2.

00:26:24 - Anthony Campolo

Suppose I give you a lot of reasons why you should pick Postgres and why Postgres is, by almost any serious DBA's perspective, the best database you could pick. If you're trying to pick something that's general and something that's going to work with most SQL, that you could host in most places, that's going to be stable, it's going to have the most features, it's always going to be Postgres, at least for the last five to ten years and for the next five to ten years.

00:26:48 - Christopher Burns

Not that I don't have time to spend working these things out. It's just a thing of like, I just need somewhere to store the data. I don't care what it does as long as it gives me the data out. I keep thinking I should look into Fauna, but then I'm like, no, no, no, don't look at that horizon.

00:27:06 - Anthony Campolo

You should look into Fauna. You should just build a really simple little proof of concept with Fauna. It's fun. Don't do it with Redwood because that'll be complicated. Build a really simple Fauna thing, just like with an Express server. You'll enjoy it. And you'll probably also realize that it's going to be very hard to build something like Ever Fund with it, but I think you'll enjoy it.

00:27:26 - Christopher Burns

Some things that this tech stack didn't cover that are also happening: the server was built in Redwood. So the Redwood API, it was built in TypeScript. TypeScript support on the server is really good. On the website, it's getting better.

The services that are running on the server are: one, the Redwood API; two, a file uploader that's separate from the Redwood API and built in Express; and three, a webhooks client built separately for certain requests. Because Redwood has size limits on some of the things that you can upload through the server, even though I'm using it on a server, it still had limits on images. For example, if I wanted to pass an image verification, like a passport, to Stripe. The first thought was, just pass it from the client. Yeah, but then you have to put your secret keys in your client. So you need to have a server as a pass-through that pulls in the files, attaches the secret keys to Stripe, and then sends them to Stripe and the data back. It's like a 200-line Express server to basically handle just the file uploads for verification.

00:28:42 - Christopher Burns

I was having problems with Stripe webhooks on Vercel with Redwood. The problem never got resolved because Redwood went, it's Vercel, Vercel went, it's Stripe, and Stripe went, it's Vercel.

00:28:59 - Anthony Campolo

That's when you just tweet Mogambo and Grouch and you say, hey, you two figure it out.

00:29:05 - Christopher Burns

Yeah. We got webhooks working in the end because, surprisingly, in our platform, if webhooks didn't work, half our application didn't work. Surprise, surprise, webhooks are important, even if you don't like them.

And it's not that I don't like them, it's that there are different ways of programming an API that's not necessarily straightforward.

00:29:29 - Anthony Campolo

Because it's more like event-based, right?

00:29:32 - Christopher Burns

Yeah.

00:29:32 - Anthony Campolo

And more function-based.

00:29:34 - Christopher Burns

You first get the event and then you need to figure out which event it is, then pass that code through that event to the function, and then you need to run that function.

00:29:44 - Anthony Campolo

But isn't that like all the JavaScript that I ever write, though? You write JavaScript all the time, so I don't understand how it doesn't feel natural to you.

00:29:51 - Christopher Burns

I guess it's because it's no longer in a Redwood service. It's in its own container where I have to decide my own patterns and UX patterns and such. But it works and there's no problems with it.

00:30:04 - Anthony Campolo

I would like to see some of this code abstracted away, if you could. A lot of the stuff that we're talking about, the architectural diagrams can only get us so far. I know you can't just share the code from your platform, but I think it would be cool to kind of see some pseudocode examples of some of this.

00:30:20 - Christopher Burns

I'm happy to share a lot of code from my platform. I would just prefer not to show the code that makes Ever Fund unique. The boring stuff I'm happy to show you if you want to see how to do permission-based roles. Be my guest.

But what else is a massive thing that Ever Fund solves? And I didn't talk about this at the Redwood meetup. Why is that important? Because say you have an application you would like to see named behind your customers' domains. Can you do that on Netlify? Do you know the answer?

00:30:59 - Anthony Campolo

I know Netlify has been slowly expanding the DNS stuff they can do at this point, but it's probably really complicated and you have to pay extra and talk to their team and work it out.

00:31:10 - Christopher Burns

It's very manual. I think you have to literally say on the forums which wildcard you want activated on which account and which site ID, so at this moment it's not like a simple interface.

00:31:22 - Anthony Campolo

But it's possible, is what you're saying.

00:31:24 - Christopher Burns

It's possible, yes. And I think Vercel is the same. But this is where people normally use proxy technologies like Nginx. The first one obviously being Nginx, second one being Caddy. Third one being, I can't remember the name. There was another one.

00:31:42 - Anthony Campolo

Apache's a big one, right?

00:31:44 - Christopher Burns

Apache.

00:31:45 - Anthony Campolo

Yeah, but I don't know if people use Apache so much for that because I know Apache, the problem is it didn't have the same kind of non-blocking IO or something like that. But you could just do this with a Node server, can't you?

00:31:55 - Christopher Burns

Well, proxying, yeah. From what I understand, this is one of the biggest questions that I have with Redwood, how much should be done for you and how much should you need to learn. Because naming your dashboard or your links behind your customers' domains, to me, is rocket science at this stage. Obviously it's possible. Obviously a lot of people do it, but not many people write about it on the internet about how they've done it. I have my sneaking suspicions on how, but that's something I'm yet to work out. That is why two sides of our clients is not fully complete yet.

00:32:59 - Anthony Campolo

To me, this is the type of stuff that I think is going to eventually be handled more smoothly by Netlify and Vercel. We're talking about now how it's possible, it's just a lot of work. I think they're going in the direction to the point where this stuff will be one-click deploy. It's just hard and takes time, and we're the guinea pigs that are helping them get there.

00:33:18 - Christopher Burns

I know it's possible, but I would still, if you look at my technology stack right now, host my two clients on Netlify and only talk to an API on my DigitalOcean stack, because that would also work out better for me. I would have far more operating room to serve more API requests than HTML requests and CSS and JavaScript. So that's something else to think about in the future.

But we need to talk about my clients. So with the original, I had two Gatsby clients, donation links and dashboard. Our new one, I have Redwood Web for our dashboard and Next.js for our donation links. The next question that I'm sure you're shouting at me right now, why two different platforms? They have different needs and you have to weigh up what need matters most.

Why is that important? Next.js, even Gatsby, even Redwood Web, they all use Apollo as the underlying language to communicate. You can build anything in any language that communicates through Apollo and talk to a server.

00:34:33 - Anthony Campolo

Well, even still, you wouldn't necessarily need Apollo if you wanted to use another GraphQL client like urql.

00:34:40 - Christopher Burns

Yes.

00:34:41 - Anthony Campolo

It's the GraphQL thing, because that's the specification.

00:34:44 - Christopher Burns

They're all still like NASA to me, though. urql and all that.

00:34:49 - Anthony Campolo

Adam Rackis has one called micro-graphql-react, something like that.

00:34:55 - Christopher Burns

If Redwood announces that they're moving away from Apollo to something like urql or something else, you would really have to show me the benefits over just a smaller bundle size at this point.

00:35:07 - Anthony Campolo

It'd be around the caching stuff, is what it's based around, that they all handle caching slightly differently.

00:35:12 - Christopher Burns

This is such a conversation. This is such a detour. What's the difference between caching and state management? I don't truly know myself.

00:35:21 - Anthony Campolo

Well, this has to do with whether your state is on your server or client, because this is what Tanner Linsley is always talking about, is that we confuse server state for client state, or that we confuse the two of them for not even being separate things at all in the first place. It's about the server. You can also cache on the client, so there's just a lot of stuff that goes into it. This is a thing that we would have to bring someone else on to talk about.

00:35:43 - Christopher Burns

Here's how I think about it. In my brain, state management is when you click toggle on, toggle off.

00:35:52 - Anthony Campolo

But what's toggling?

00:35:53 - Christopher Burns

But in the background, that is pulling data from an API. For us it's live mode and not live mode. And then the difference is you toggle live mode on and then off and then back on. That third time, that data is going to come from your cache, not an API request, from what I understand at this stage in my developer career. Massive subjects that we're not going to get into right here.

State management: Redwood uses just standard context and hooks. Our Next.js client uses Pullstate.

00:36:32 - Anthony Campolo

And when you say Pullstate, is Pullstate a library? Is it a pattern? What does that mean?

00:36:36 - Christopher Burns

It's a library. It's a state management library. Saw some geezer on Reddit suggest it. I went ahead and implemented it for our Next.js app. It's more of a global context kind of state.

00:36:51 - Anthony Campolo

And you're telling me there's another state management library that I've never even heard of? I can't believe that I thought I knew about all of them.

00:36:57 - Christopher Burns

I do recommend Pullstate. It's really easy. Like, really easy.

00:37:03 - Anthony Campolo

Easier than easy peasy.

00:37:05 - Christopher Burns

Don't ask me what easy peasy is.

00:37:07 - Anthony Campolo

Yeah, it's like, what about Overmind, bro?

00:37:09 - Christopher Burns

Okay, okay. Easy to me is you put a provider at the top and then you call the rest with hooks. That's easy to me. State management and caching to me is NASA. If you ask me how they work, I do not know.

00:37:27 - Anthony Campolo

But that would be the argument. If you're asking what's the benefit, the benefit is switching from Apollo to urql or whatever is happening in the caching layer would be easier for the Redwood developer. The Redwood developer would not have to think about cache because there would be something baked into the framework that is caching the way that fits a Redwood app. That is the discussion that is happening, as far as I understand it.

00:37:51 - Christopher Burns

And this is a question and it's an opinionated question. Should all state be managed by the server?

00:37:57 - Anthony Campolo

I would say, good luck. Turning that back around is what I would say to that.

00:38:01 - Christopher Burns

Okay, you toggle a dropdown obviously does not need to be managed by a server, but I mean, what color scheme do they have set as a preference? Something that you'd normally stick in cookies or a state management library. You're more just going to manage it from the server back and forth every time they change something. It's questionable. Obviously there's no right answer. It's up to the application and we all choose differently.

Back to the point of our client. Why did we use Redwood? Because of the benefits of the auth library to log in to our dashboard. The router was good with the private links obviously working in useAuth. And the other thing is the scaffolding.

You think about building applications. You think an API and a user interface, they're about 50/50. They are not. To build a user interface is more like 70/30. Change my mind, Anthony.

00:39:02 - Anthony Campolo

Wait, do I have to? Sorry, I zoned out for a second. I didn't listen to the last 10 seconds of the thing you said. Spin it back and ask me that again.

00:39:10 - Christopher Burns

It's a lot harder to build a user interface. To build an application, you're going to spend 30% on your API and 70% on your user interfaces. Change my mind.

00:39:23 - Anthony Campolo

It depends how user interface heavy your application is.

00:39:27 - Christopher Burns

A standard web app, forms, graphs, and the good old thing of searches.

00:39:33 - Anthony Campolo

Well, that's a great question. I would say it depends how complicated the searching is, because that's the one thing that still can't really be done on the client side, because you can't ship the whole database to the client.

00:39:43 - Christopher Burns

Oh, we're going to talk about that in a minute because obviously that's something I've done.

00:39:47 - Anthony Campolo

Ship the whole database to the client.

00:39:50 - Christopher Burns

No, sadly not. But you could using something like Algolia. Not the whole database, but a graph.

00:39:56 - Anthony Campolo

Right. Yeah. That's search as a service.

00:39:59 - Christopher Burns

Search as a service, yes. We'll talk about these things in a minute because I have multiple experiences in that. But we need to speak about our second client, our donation links, and why they're important, why they currently sit on Vercel. They're built in Next.js. One of the big features of Next.js is...

00:40:20 - Anthony Campolo

Incremental static site generation.

00:40:23 - Christopher Burns

Awesome acronym, something like that.

00:40:25 - Anthony Campolo

You don't want to have to build 9,000 pages every time you change one of them.

00:40:29 - Christopher Burns

Exactly. As I said earlier with Gatsby, I have 2,000 donation links. What happens now? As soon as the Next.js client fetches that page, bam, the updates are there. No rebuilds.

The only caveat that I've seen right now is that it requires someone to refresh the page first. So say the database updates in the background. I go to the page, I will see the old changes. I refresh the page, and then I'll see the new changes from the incremental static site generation. That may be because I'm not fully configuring the Next.js settings properly yet, but a lot of it is magic, and I think it's amazing what I've done so far.

This brought up a really good point in my talk where I said, every time you're working on something in a business for a client, you need to evaluate your options and pick the best one that works for each client. For example, donation links worked better in Next.js, and our dashboard works better in Redwood. I think it will stay that way for some time.

00:41:37 - Christopher Burns

On our tech stack picture, I drew two nice little boxes: one saying everything hosted on DigitalOcean. That is pretty much everything, and everything hosted on Vercel. That is just our donation links.

In the future, we're going to be moving our donation links into our DigitalOcean account. We're going to be adding it to our monolith. But before we do that, we also really want to work out proxying SSL certificates and allowing our customers to use our short links behind their own URLs. That's something I've not fully figured out yet. If someone knows how to do that in Nginx and have HTTPS certificates and all that sorted out, I would really like to know how you do that.

We also have, just to round out the picture, three other services built into our product. That is Magic Links for the auth provider, Postmark for emails, and Stripe for payments. What do you think, Anthony?

00:43:05 - Anthony Campolo

I think we could do a whole separate episode in terms of integrating third-party services and what that means. I can imagine that you would have spent a lot of time looking at different auth providers and maybe looked at Braintree instead of Stripe. I think what we talked about now is probably good to close it out in terms of the actual architecture, but I know that the third-party services aspect is a really huge topic that I would like to delve into as its own subject.

00:43:33 - Christopher Burns

Yes, that was our quick tech stack. But what are some cool extras that have been built into our second version that I think were really easy because Redwood handled a lot of the boilerplate technical wealth for me? Team management, Magic Links, auth providers, better error handling. Error handling is set up on our clients and our API using AppSignal. It gives a really nice dashboard of how everything's looking in terms of request times and everything.

We also have user logs, so every time a service is called, we log who ran the service, what their IP was, and what data they tried to retrieve. And RBAC. But I also think it's by a different name than RBAC, CA or something like that. Someone said about it on the Redwood community that it's not RBAC, it's something else. It's basically like permissions.

00:44:30 - Anthony Campolo

It's just a library called CASL, an isomorphic authorization JavaScript library, which restricts what resources a given user is allowed to access.

00:44:39 - Christopher Burns

Okay. I've done RBAC with roles and permissions, whatever that's called. I do not know.

00:44:47 - Anthony Campolo

Yeah. So that's authn plus authz. This is why I say we need to do a whole auth episode where we actually research and define all these terms. I want to get David Theisen on to talk about this stuff.

00:44:57 - Christopher Burns

David Theisen is a legend. He helped build the Redwood RBAC. So whatever I've built is whatever Anthony just said. I can't tell you what it is. It basically does role authentication and permission authentication, all custom-built from our database.

At this point, I showed a demo of Ever Fund, a nice little slice. And then I said two statistics: how many devs it took to build this, and I said one developer and four months. What was your reaction to that, Anthony?

00:45:29 - Anthony Campolo

Which developer was it?

00:45:31 - Christopher Burns

Me.

00:45:32 - Anthony Campolo

That was the drop the mic moment. It was great. I could hear the crowd gasp over my streaming service.

00:45:37 - Christopher Burns

Do I even remember? Even Tom Preston-Werner gasped. And he's seen a lot in his time.

00:45:43 - Anthony Campolo

Sure. Yeah, we'll go with that.

00:45:44 - Christopher Burns

He's seen a lot. We've all seen a lot. Even David gasped. But yes, I've sacrificed a lot of my time to get this out. It wouldn't have been possible without Redwood and the people that have helped throughout my Redwood time. I will carry on bugging them in the future with Redwood things. That was basically the whole talk. So I spoke a lot, obviously.

00:46:07 - Anthony Campolo

And what's funny too is we've been talking about this throughout the course of the whole show at this point. Some of this is even rehashed from what we've talked about in the past. But I think it's great because it shows how you have to keep going over these ideas on multiple levels. For you, this is the tech you were living with for months at a time. For you to explain to someone all of the things that go inside, it's just not possible. You're compressing so much information.

So I think it's great to have these different resources. People can watch your talk, listen to this episode, and look at your diagrams. Hopefully people can start to get a sense of what it really takes to build one of these applications. This was a super fun conversation. We're going to have Brandon from Blitz coming on for the episode after this one, so that'll be really fun.

00:46:54 - Anthony Campolo

We'll get to talk a little bit about Redwood and Blitz, how they relate to each other, how they are different, how they may be going at things from similar or different angles. There's a lot to dive in there, and I think listeners will find that one pretty interesting.

00:47:09 - Christopher Burns

My last question for you, Anthony, is this was my first technology talk. Should I do more?

00:47:17 - Anthony Campolo

If you had this be the only one you ever did, then you could at least go out on a high note. But yeah, no, I think obviously I'm someone who goes out and does talks like every week now, almost. So I am a big fan of them. I think it's a great way to share knowledge, but also build credibility and hopefully get the word out about cool stuff you're working on, which in your case is Ever Fund.

00:47:39 - Christopher Burns

I'm working on a lot of cool stuff that is making me gray. I have a lot of gray hair and I'm only 24. It's always picked out by my partner.

00:47:48 - Anthony Campolo

But now that the application is up and running, you don't have to do anything else, right? Everything just works forever and you never have to think about it, right? Right.

00:47:56 - Christopher Burns

Sadly not, because this is only our soft launch and it's not got every feature that we require to fully launch it.

00:48:03 - Anthony Campolo

So you're not worried about ops, so you're not worried about crashing at 2 a.m.?

00:48:07 - Christopher Burns

Yeah, we have customers using it. I like to abstract as much responsibility away as possible.

00:48:12 - Anthony Campolo

Apparently even Amazon can't keep that up these days, so good luck with that.

00:48:17 - Christopher Burns

Well, that's why you just host it by yourself on DigitalOcean. So even if Amazon falls, you don't. Because if I remember rightly, Netlify went down with Amazon.

00:48:27 - Anthony Campolo

Yeah. Netlify, I believe, is in us-east-1, so that would have been like all of Netlify.

00:48:33 - Christopher Burns

All of Netlify is in us-east-1.

00:48:35 - Anthony Campolo

I don't know about all of Netlify. No, so all of Netlify is not in us-east-1. But if you are using functions on the free plan, all of your functions are in us-east-1. So they have a huge dependency on us-east-1 that a lot of their services rely on. But they have a globally distributed CDN. That's the whole point. They're not all in us-east-1.

00:48:56 - Christopher Burns

I love American tech companies. I think they're the center of the universe with West Coast servers. This is my final comment. We use a provider. We love the service. It's perfect. But they're hosted in us-west-2. So that's California.

00:49:14 - Anthony Campolo

I have no idea which one that is.

00:49:15 - Christopher Burns

But the biggest thing is I live in Brighton, United Kingdom. That's halfway across the planet.

00:49:21 - Anthony Campolo

Yeah. It's like you and me talking to each other.

00:49:24 - Christopher Burns

And I'm complaining about one-second delays from sending something to California and back. The internet is amazing, but you sometimes forget how far data can travel there and back in one second.

00:49:41 - Anthony Campolo

It takes about 100 milliseconds to make that hop at just the speed of light itself. And because of TLS handshakes, you have to do a couple of those. That's why you're going to end up with a noticeable latency almost no matter what.

00:49:52 - Christopher Burns

But come on, halfway across the world and I'm complaining about a one-second latency.

00:49:59 - Anthony Campolo

What can happen in a second?

00:50:01 - Christopher Burns

That's it for this episode. I'm just going to say it again. If you've never put faces to names, Anthony is AJC Webdev on Twitter and I am Burned Chris on Twitter. Or you can follow our main Twitter account, FSJamOrg, where we normally post updates about the frameworks and what's going on around us.

00:50:25 - Anthony Campolo

But no one can see your face right now. You're putting a voice to a name.

00:50:29 - Christopher Burns

Well, you can put a voice to a name on our Twitter profiles. I'm just going to do one more tease. We have almost confirmed our Christmas New Year podcast, and it's going to be a really good one. It will be our first roundtable podcast. We are hoping that we're going to see representatives from Redwood, Bison, and Blitz for a nice, wholesome Christmas community. We'll talk about where we hope to take JavaScript in 2021. That's everything.

00:51:10 - Anthony Campolo

By the way. [inaudible]

00:51:47 - Anthony Campolo

I heard that you slapped him in the face and said, "I do what I want." No, you guys don't even live in the same country. How would anyone say that?

On this pageJump to section