Supabase – Realtime: Multiplayer Edition
supabase.com
supabase.com
I almost want to scrap all of my code and move it to Supabase. Congrats to the team on this launch, very cool.
edit: actually, after thinking it through, I'm not clear on what Supabase is calling multiplayer. Presence is one thing, but when I think multiplayer, I'm thinking conflict resolution. Is this an OT/CRDT implementation? Or is it just presence?
… general availability of Realtime's multiplayer features, Broadcast and Presence.
- 25 concurrent channels
- 25 channel joins per second
- 200 concurrent connections
- 100 broadcast messages per second avg over 60 seconds (not including db changes) (aka 6,000 per minute rolling)
I think these are probably pretty close to where we'll land for free projects. They can be changed per project so if you (or anyone) needs a limit increased in the short term we can do that.
Im Steven, co-founder of Liveblocks. Thanks for your feedback on pricing. We try to have a fair pricing for everyone and for companies of all sizes.
We’re working on a new pricing that will make this much more affordable, even free in most cases.
Would love to get your feedback on that if you’re up for it?
Thanks!
I like the simplicity and clarity of just directly charging for the valuable thing. Nothing wrong with the other models, they just aren't for us.
Supabase and Replicache can absolutely help with (1). But for (2) you will need OT or CRDT.
https://docs.yjs.dev/getting-started/a-collaborative-editor is a good place to start - it uses Quill and CRDTs for (2) and can have a persistence layer built in (or custom written, to work on top of Supabase etc.) for (1).
It's written by the team behind https://tiptap.dev, which is an amazing WYSIWYG text editor, but HocusPocus does a great job of syncing state of a variety of WYSIWYG editors out of the box. Getting the server running is a couple of minutes worth of work and scaling it is quite easy.
In addition to editor state, it also has built-in support for 'Awareness' (info on current users), as well as any other Y.js datatype, including other things with a bridge into Y.js.
edit: also, I couldn't get a good look at their documentation outside of the paywall, so I have no idea how they implement the backend. It's important, because I need to persist my documents as html strings, not as y docs.
So I’ve had to implement a system where a new yDoc is created when the session begins, and then is converted back into a string when the session ends.
Did you have to do anything similar? And if so was it easy with hocuspocus? I wasn’t able to get a clear answer from the docs.
I'm not completely sure, but I think at ProseMirror they're using Yjs [2] for the collaborative editing part. If not, checking out Yjs is worth it in and of itself.
> Yjs is a CRDT implementation that exposes its internal data structure as shared types. Shared types are common data types like Map or Array with superpowers: changes are automatically distributed to other peers and merged without merge conflicts.
> Yjs is network agnostic (p2p!), supports many existing rich text editors, offline editing, version snapshots, undo/redo and shared cursors. It scales well with an unlimited number of users and is well suited for even large documents.
> Conflict-free replicated data types (CRDT) for collaborative editing are an alternative approach to operational transformation (OT). [3]
OT was what Google Wave was based on and I think current colab editing in Google Docs and other of their office products use this.
[0] https://prosemirror.net/examples/collab/#edit-Example
[1] https://marijnhaverbeke.nl/blog/collaborative-editing.html
No, ProseMirror has its own approach to sync.
> OT was what Google Wave was based on and I think current colab editing in Google Docs and other of their office products use this.
Yep.
The team behind TipTap (built on top of ProseMirror), created the Hocuspocus server backend for Yjs and collaborative text editing.
My real trouble is the fact that this is an existing application, with hundreds of thousands of pre-existing documents, all stored as html strings. I've been trying to extract the html on the server, but it's incredibly difficult. I've actually given up for the time being, and using a hacky workaround.
https://elixir-lang.org/blog/2020/11/17/real-time-collaborat...
https://www.youtube.com/watch?v=HTB4mQyMAmg
And supabase uses elixir to listen to database changes and push then over websockets.
Happy to have a chat on collaborative editing anytime if that'd be helpful (email in profile).
Phoenix Framework gives you presence and CDRTs out of the box. I’m not sure if they’re also using Phoenix, but there’s a well-known, heavily used open source solution for the core of this offering and I’d be shocked if they didn’t at least study and/or borrow from it.
Edit: yep, according to the page they’re advised by Chris McCord, the creator of Phoenix.
we're excited about this release - it adds a few neat features to our Realtime server[0]. For those who don't read the post (it's quite long), our Realtime server was initially built for subscribing to Postgres changes via websockets. We've added Broadcast functionality (for "ephemeral" messages that don't need to be persisted to Postgres) and Presence (similar to Broadcasts, but it retains an eventually-consistent state between users).
We were planning a larger write-up with all the technical details but it became a bit long. Some highlights:
- Realtime is built with Elixir an Phoenix[1]
- We've moved to a single, global cluster - We're using `Phoenix.Tracker` to globally distribute the Erlang PIDs of all of our Postgres connections. This guarantees there is only a single connection to each database.
- We've implemented a "leaky-bucket" rate-limiter using Erlang's `:counters` module[3] for "per tenant" rate-limiting. We'll move this to a global rate-limiter in the future
- We're currently seeing ~2000 concurrent connected users - it will be interesting to see what this spikes up to now that this is on HN
It's still in heavy development, and we'll make sure to detail all the choices we take as we continue solve problems. A few of the Realtime team will be here answer questions - @chasers, @wenbo, @abc3erl.
[0] Realtime: https://github.com/supabase/realtime
[1] Phoenix Framework: https://www.phoenixframework.org/
[2] rate limiter: https://en.wikipedia.org/wiki/Leaky_bucket
[3] :counters: https://www.erlang.org/doc/man/counters.html
Temporal has done an incredible job of ensuring there will be no side-effects (even with external systems), so I doubt we'll be able to do something as extensive as they have. That said, we will probably build a simple Postgres queue/workflow engine (similar to pgboss[0]). It will live in the Postgres database (as an extension), but will be nicely integrated with Edge Functions. We haven't started this yet, so I don't have any timelines.
[0] pgboss: https://github.com/timgit/pg-boss
The reason we paused it was the realisation that it's far more powerful to co-locate this sort of product with the data. In this case, Workflows would be more powerful as a Postgres extension - you can store the workflows into your database, create them using SQL, and the workflows would have direct access to your operational data. We'll probably re-write this using pgx[0] at some stage (if anyone is reading this and wants to attempt this, please reach out).
[0] pgx: https://github.com/tcdi/pgx
The code is already open source, and anyone can extract it into a more reusable package. And it's developed in the open, anyone can fork or send PRs or anything. That's what open sourcing a piece of code is really about.
Creating dev and staging environments is a feature that I am most looking forward to. Hopefully that is on the road map.
I say that because I just used Supabase for the first time, and I was able to build and launch the Slack clone in ~15 minutes. Seriously cool. Thank you for sharing
What are the chances of an official C# library being in the works? I think this would greatly fill the needs for unity devs. I use firebase on almost all game backends because of how quickly I can get set up with auth and a db.
I used supabase in my latest project and it served my needs but there were a few difficulties to overcome. The greatest shortcoming was the lack of real time support (C#), and I had to do everything via REST api.
I am planning on publishing the game as OSS and making some learning videos about it
https://github.com/supabase-community/#client-libraries
They won't support the functionality we outline in our blog post yet (we are still figuring it out on our official JS libraries), but I'll send him your message.
As an aside, if anyone is reading this and wants to help maintain the C# libraries, please reach out.
[0] acupofjose: https://github.com/orgs/supabase-community/people/acupofjose
If no connection exists yet, you're right, two connections could try to establish themselves at the same time. In which case, whoever gets to the db first wins. But then the loser is still connected to PubSub, so they'll now start getting changes just the same.
Does the global cluster architecture make it much harder to self-host supabase? Not that I plan to, but having the promise of portability is really important.
Of course the latency can go up with load but it shouldn't get very spiky thanks to the preemptive multitasking.
Anyone from Supabase here, do you have any plans to build in support for CRDT toolkits such as Yjs or AutoMerge for these features? It would make working with them so much easer if there was a plug and play backend.
The one other thing I would love to see next from them is an offline sync product, so you could partially sync a users dataset to their device and save back any changes later (bonus points for then combing that with CRDTs). Maybe the WASM Postgres yesterday [0] could be a foundation for such a product.
It's definitely something we'll support (we mention it briefly in the blog post). We'll extend this service so that it works well with WebRTC, and we have a few ideas for making it easy for development.
> Maybe the WASM Postgres yesterday
This was mind-blowing! Very cool what the crunchy team have done there. It would be awesome to replicate from a remote Postgres database to a "per-user" database to the browser. I think WASM support needs to improve before it can become generally useful for offline-sync, but the tech seems withing reach.
We're working on various ideas for offline-sync, but the Realtime server will be central to whatever implementation we land on.
I previously experimented with building an offline syncing CRDT db using Pouch/CouchDB and combining it with Yjs for automatic conflict resolution. But Postgres would be so much better as the foundation. If only I had time it is something I would love to work on…
I assumed it was related to https://docs.timescale.com/timescaledb/latest/how-to-guides/... (even though we were only running it single-node, my understanding is that Realtime works by tapping into the replication feed)
> Using logical replication with TimescaleDB is not recommended, as it requires schema synchronization between the primary and replica nodes and replicating partition root tables, which are not currently supported.
As long as logical replication is supported, this won't be an issue for Realtime because the purpose is to receive data changes (which come in a JSON format) and the end-user doesn't need to persist schema modifications.
> but couldn't get it working
If you send me some error logs, I can take a look or forward to one of the team.
> support Postgres streaming replication
This is the first time I've heard it requested - I don't think it's something we'd do unless there was a good reason and strong demand. If we were to do any work in this direction we'd prefer to try contribute DDL streaming to PostgreSQL's logical streaming. We've been thinking about this for a while (Michel has built metagration - https://github.com/michelp/metagration which has prompted a few ideas for core patches)
I really appreciate the offer. I don't have the logs handy unfortunately and haven't been interacting with the Timescale instance in a few months. If I move back to that side of things I most definitely will take you up on that.
For what it's worth, I don't think the error was in running or connecting to Realtime; rather, I think what happened is there were duplicate, missing, or truncated messages. Thinking on it some more, I think TimescaleDB is using multiple tables under the hood for the tables they expose. Unfortunately, it's out of my depth of Postgres knowledge right now, so I can't tell you more
Are you also working on optimistic updates (which may be related to offline-sync)?
But yes, optimistic updates is one of the requirements. In the meantime, if you need something great, I can recommend Replicache and WatermelonDB - both are excellent.
Nice, thank you.
EDIT: Googling around yields a somewhat hostile discussion from last year: https://news.ycombinator.com/item?id=26637360
... but it looks like you _can_ self-host? https://supabase.com/docs/guides/hosting/docker
> difference between Supabase open-source and the paid versions
On the paid version we handle some of additional database management (like daily backups, PITR, etc). These are technically available for self-hosting too, because the database is just a Postgres database, but I point it out here because it's not something you'll get "out of the box" from the Docker setup.
Our philosophy with open source is "offer everything" and then charge for usage. There aren't any features completely gated. Our Enterprise plan just adds additional SLAs and support packages for our cloud platform.
In addition to the self-hosting docs you've linked, in our GitHub you can find the Docker files[0] and some community-developed self-hosting strategies [2]
[0]https://supabase.com/blog/supabase-studio
[1] docker: https://github.com/supabase/supabase/tree/master/docker
[2] community: https://github.com/supabase-community/#self-hosting
Definitely trying you guys out now.
Doesn't seem portable at all. If you make your own code, you can move it wherever you want in whatever system you want. It seems like if you use this product, it will get you stuck in that environment and if you need to upgrade, then you are going to have to do the work later on anyways.
What exactly is so great about this product? I'm not saying its bad, I'm just not fully understanding the advantages of using it?
Why would someone want to use this over something like a framework for the backend (that is free) and a database they want and then host it wherever they want? I don't really get why someone who knows how to code would want to pay extra money to build a backend.
Yes, which is great sometimes.
> I don't really get why someone who knows how to code would want to pay extra money to build a backend.
Because reinventing the wheel isn't the best use of time. It's more fun to work on interesting problems than yet another backend, again.
> Doesn't seem portable at all. If you make your own code, you can move it wherever you want in whatever system you want
You realize it is all open source and can be self-hosted, right?
Also, I don't have to worry about my code being terrible, either.
Quickly skimming the docs, I don't see any examples of this.
Server authority and some of this security can be added app level but I think the message throttling needs to be built in if its going to support any kind of pvp/untrusted peer scenario.
Anyone know the story there?
Broadcast permissions is currently not handled by the server and left to the developer to implement. We have discussed this internally and will prioritize Broadcast authorization accordingly because we've gotten feedback about this from a number of developers.
> Can users be kicked from a channel?
Not at the moment but again we've gotten feedback about this as well and will prioritize it.
> Is message spam/flooding/DDOSing users in a channel protected?
We have built rate limiting and other protections so bad actors don't affect the good in the cluster. A colleague of mine posted these limitations of Supabase Realtime to prevent abuse: https://news.ycombinator.com/item?id=32511586.
(Comment also acts as a bookmark) :)
[v] Can host myself
[v] Can access from China (since Firebase is blocked)
[v] ...anything else?
(Btw they should put this in FAQ or something)
Also, every single person on the Supabase team actively does support so if you would like world class support than look no further!
Supabase + SvelteKit + Cloudflare
I'm super curious about realtime multiplayer solutions (and I don't think I'm alone). But I find a great lack of info on what running this kind of app would cost. I come from the old-school hold-no-state, request->response->gtfo mentality, and I always have the _feeling_ that it'd be expensive to scale. Not just holding the websocket open, but how much effort do you expend parsing the WAL? How chatty is that kind of persistence mechanism? What other 'gotchas' are there etc.
I'd love nothing more than to dispel that vague feeling with data. I know it wouldn't come close to a full performance analysis, but throwing a few datapoints on a chart would help get a ballpark idea and tune my hype->action conversion.
I could nail down a pile of questions, but I'm sure you know better than I how to measure your own systems. But roughly I'm wondering: - how many users did you have? - how much traffic did you get? - how much would/did it cost to host on supabase? - how much resources did the database/realtime components consume?
Congrats again on the launch and have a nice weekend.
All I know is that it has a real time server and multiplayer. Sounds like a game.
> Supabase is an open source Firebase alternative. Start your project with a Postgres Database, Authentication, instant APIs, Realtime subscriptions and Storage.
Our docs give details about the architecture for each project: https://supabase.com/docs/architecture
https://supabase.com/blog/supabase-realtime-multiplayer-gene...
If so, y'all might want to look into: https://github.com/elixir-ecto/postgrex/blob/master/lib/post...
Where can I see that in the code? Or is not quite out yet?
We plan to move all the code over to https://github.com/supabase/realtime in the next couple of weeks and you'll be able to see the code in its entirety.
We actually use https://github.com/supabase/walrus to get the database changes and we're planning on moving to a Rust worker (https://github.com/supabase/walrus/tree/worker/worker) for better performance especially in the RLS-enabled use case.
I promised José that I would check out Postgrex.ReplicationConnection and we might add it in to our Supabase Realtime some time in the future.
There are some community-developed libraries here: https://github.com/supabase-community. We sponsor developers to maintain these - at some point we'll hire someone to work full-time on these (and we'll start with iOS/Android)
Cool announcements for Pinecone, PlanetScale and Supabase.
Android 11 | Chrome 104
That back button glitch is specific to the demo. We had to do a few redirects based on Presence sync and load balancing each room. I'm sure there's a better way of doing it and will seek to improve it when I update it. Sorry about that!
> Supabase is an open source Firebase alternative. Start your project with a Postgres Database, Authentication, instant APIs, Realtime subscriptions and Storage.
Client will seek to continuously reconnect to the WebSocket when there's a connection issue and server must receive at least one heartbeat in a 60 second window; otherwise it will clean up the WebSocket connection.
We built Supabase Realtime on top of Phoenix Channel, and along with our clients, handles unreliable network connections gracefully, including on mobile.
"Phoenix uses an at-most-once strategy when sending messages to clients. If the client is offline and misses the message, Phoenix won't resend it. Phoenix doesn't persist messages on the server. If the server restarts, unsent messages will be gone. If our application needs stronger guarantees around message delivery, we'll need to write that code ourselves. Common approaches involve persisting messages on the server and having clients request missing messages. For an example, see Chris McCord's Phoenix training: client code and server code."
https://hexdocs.pm/phoenix/channels.html
It will be impossible to build a reliable mobile experience on top of such shaky foundations.
This is true but you can store your messages inside your database and on reconnect you can fetch the messages you missed.
Just want to confirm that we did put in place a client-side character limit.
Screen recording, with latency around 90: https://imgur.com/a/5FU3paR