Architecture best practices: Remix/Supabase

Hey all, I’m CTO of SaaS startup that makes an ERP with Remix (SSR), Redis, and Supabase (Postgres).

The tricky part is that each customer gets their own database, redis instance and remix app (the remix app has secrets that point to the unique database).

I think that because of fly.io’s partnership with Supabase (for managed Postgres) fly.io makes a lot of sense (in theory I can have each app/redis/postgres in the same data center).

But I’m not sure how to go about this with fly. In the examples I’ve seen, there is a single fly.toml and dockerfile. But I’m not sure how to make fly work with a fanout approach. Looking for any tips on best practices. It seems like FlyCD is meant for a single deployment (as opposed to many).

I’ve done this kind of thing before with CDK, but I’m hoping to avoid it if possible. Appreciate any advice you can give!

I’ve got a longer blog post that is still in the draft stage describing an app of mine in which each user gets their own database, in my case I bring up one redis instance per region and it is shared within the region using prefixes, and there are many other differences, but overall a number of things I learned would apply to your situation.

To start with, it worth realizing that flyctl is just an application built upon the fly.io Machines API and GraphQL, and fly.toml is just a place for default CLI arguments to save you some typing. You actually don’t need either, but you probably will find flyctl useful.

So the first step is to be prepared to write some small scripts. All you need is import { spawn } from 'node:child_process' and fetch. That will get you up and running.

For me, it was then worth taking the next step. Since I know how to write a web application, and deployment is a matter of running a script, I created an administrative interface that I use. I now can add new users from my smartphone.

1 Like

Thanks a lot for great explanation! I do the same the same pretty much with supabase, using execa in a script to set the environment variables for each child process. But this all seemed a bit intimidating before your explanation. Really appreciate you @rubys

I think that’s a great point about regional Redis too. Any chance you can share a little script code? No worries if not.

Not sure it would be helpful. The app itself uses Rails. The code is here: GitHub - rubys/showcase: Ballroom Dance Showcase Scheduler ; there is mention of Redis in the README.

There is a brief mention of prefixes in the redis docs: Redis Pub/Sub | Redis

Rails formalizes this: Action Cable Overview — Ruby on Rails Guides

Hi @barbinbrad I’m the owner of FlyCD. At the moment FlyCD works by matching a single repository to a project. A project would have one app for production, and multiple apps to represent preview/staging apps. For monorepo cases, it distinguishes based on the path.

Your use case wouldn’t work out of the box with FlyCD, but I’m happy to discuss more and see how I can support you on getting FlyCD to work for you. You could get a customised, dedicated instance of FlyCD, or we could consult and build a custom, one-off scripts you can use manage yourself, in your own CI pipeline.
Feel free to reach to me via email: peter @ flycd.dev (without the spaces).

1 Like

Hey Peter, thanks so much for reaching out! First of all, congratulations on the awesome product (FlyCD). That’s very generous of you to offer to help.

1 Like

@rubys how do you handle this problem: the fly.toml needs to be different for each customer (for the region). Or am I misunderstanding that?

Do you just edit the file as the script runs? (In the early stage)

The API doesn’t use fly.toml at all. flyctl uses it to provide answers to things you don’t provide as parameters. If you find a case where there is a flyctl command that needs fly.toml, let us know.

Ahh, I see. Thanks!

you can pass the region via cli flags and it’ll override what’s in the fly.toml (I assume you’re using the cli via a bash script). Otherwise, you can do them via API as suggested earlier

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.