24 ms·
Run Ordinary Rails Apps Globally (2021)
- louissm_it 5y agoFly is compelling enough to use without all the global deployment options they offer[1] but it's assuring to know if you ever do need to deploy globally, they can support that better than most. [1] - https://github.com/superfly/fly-ruby https://github.com/superfly/fly-ruby
- photon12 5y agoAmazing what started with Heroku* has turned into. *Started for me at least. Heroku was how I got started as a Rails developer, and it made it so easy to get a deployment available to interact with from anywhere.
- hrdwdmrbl 5y agoNice to see that they support HTTP/2 (which BTW is 6 years old now), unlike Heroku
- j4yav 5y agoThat is a very clever implementation, and indeed feels like magic for someone who makes relatively small Rails apps.
- undecisive 5y agoAlas, I feel like the word "Ordinary" is doing a lot of heavy lifting in this title! The upshot is, so long as your postgres + rails app isn't doing some kind of DB write with every request, and doesn't do much - or ideally anything - with Redis, and you want 200ms time-to-first-byte globally (or at least, in multiple locations across the world) then you can easily get better performance with Fly.io than most other solutions. It's a really clever solution, and one day I'd love to work on a project that fulfils all of those constraints. Haven't found one yet though.
- abofh 5y agoYou posting on this website is a thing it totally matches, it's just the value proposition keeping you from big VC bucks
- undecisive 5y agoAbsolutely agree! (Though... I suspect there may be some other caching tech in there to help handle the load, and I don't think Fly.io would be cost effective enough for HN - would be interested to know for sure though) But if we are being honest with ourselves, HN is very much a featherweight unicorn in an ocean of lumbering behemoths. And that's part of the attraction for this particular crowd. Would be interested in other high-profile rare cases, like HN.
- sudhirj 5y agoRunning a Fly app backed by DynamoDB Global Tables is an option. DDB keeps a copy of your data in all the regions you specify, each Fly instance can connect to the nearest region, and writes are propagated with eventual consistency & last write wins. And most Redis commands can be mapped to DDB, I worked on a lib to do that. https://github.com/dbProjectRED/redimo.go https://github.com/dbProjectRED/redimo.go https://github.com/sudhirj/aws-regions.go https://github.com/sudhirj/aws-regions.go https://aws.amazon.com/dynamodb/global-tables/ https://aws.amazon.com/dynamodb/global-tables/
- thrwn_frthr_awy 5y agoDoes DynamoDB give transactions, rollbacks, joins?
- sudhirj 5y agoYes, you can apply a set of updates atomically so they all fail or none, with conditions. No save points or nested transactions, though. And the transactions need to be grouped into a single request. Joins, no. Most of the NoSQL systems distribute data by partitioning them on the primary key, and give you scalability by not doing any work across partitions. Which means that traditional joins won’t be supported. You can either join the application, or maintain a secondary schema that has your joined data organised in the access pattern you plan to use. Google DynamoDB Alex DeBrie or Rick Houlihan for a ton of tutorials on how to restructure data for partitioned/distributed NoSQL systems.
- qaq 5y agoand max 100 keys in a transaction or whatever the limit is
- mhoad 5y agoThe other option here is using Spanner from Google (https://cloud.google.com/spanner https://cloud.google.com/spanner) which now has full PostgreSQL compatibility. That gets you global scalability with minimal meaningful changes to your application at all. They even made a Rails specific guide for it here https://cloud.google.com/blog/topics/developers-practitioners/scale-your-ruby-applications-active-record-support-cloud-spanner https://cloud.google.com/blog/topics/developers-practitioner... If you combined that with say Cloud Native Buildpacks (buildpacks.io) and Cloud Run you now have basically an infinitely scalable solution that happens to hook into all of Google’s infrastructure at just the right points that requires almost zero work on your behalf. Plus you get to keep the one command to deploy that a lot of the Rails community is used to from the Heroku days. No K8s to configure, no servers to maintain, per second billing on your app server, everything autoscales, very little to learn in the way of new technology. You can complicate things at your own pace as far as the rest of “the cloud” goes but there’s no need to do so unless you want to. It’s a pretty sweet deal in terms of cost to benefit ratios.
- nickjj 5y ago> The upshot is, so long as your postgres + rails app isn't doing some kind of DB write with every request, and doesn't do much - or ideally anything - with Redis Yeah that's the thing I never understood about Fly. Globally scaling a stateless web app is very nice to reduce latency but what happens when you have your web apps in US West, US East, EU, India and Australia but Postgres and Redis are sitting in US East. Anytime you perform a DB / Redis write aren't you back to waiting 70ms-300ms depending on where in the world you are? Background jobs that flow through Postgres or Redis are super common in a bunch of tech stacks (even Elixir / Phoenix with Oban), and with Rails specifically any type of websocket broadcast goes through Redis too which kind of defeats the purpose of trying to achieve low latency websocket connections since every broadcast goes through Redis in US East while your web servers are around the globe. Am I missing something important here? Personally I haven't developed a single web app in the last 8 or so years that didn't heavily use Postgres and / or Redis. These are mostly Flask, Rails, Django and Phoenix apps. I want to like Fly but every time I think about the above I talk myself out of considering it because each web app instance costs money. If you have let's say 6 instances spread across the globe with 1 dedicated CPU + 2 GB of memory each that's $31 x 6 ($186) just for your apps on Fly[0]. If you can't get around high latency for DB / Redis writes and writes are fairly common, it's a hard sell to pay $186 / month for that when you can get a 1 CPU + 2 GB VPS on DigitalOcean[1] for $10 / month and not think about globally distributing your web apps. I get that the $186 vs $10 isn't a totally fair comparison because with Fly you're getting 6 CPUs and 12 GB of compute while with DO you're getting 1 CPU and 2 GB but with Fly even if your app can happily run with 1 CPU + 2 GB of memory you have to pay for each distributed instance if you want that global reach. With DO you have the option to use that single $10 / month VPS to run your app and forget the idea of global distribution, so if your app fits on that instance size it really is directly and fairly comparing $186 vs $10. [0]: https://fly.io/docs/about/pricing/ https://fly.io/docs/about/pricing/ [1]: https://www.digitalocean.com/pricing https://www.digitalocean.com/pricing
- ignoramous 5y agoLike you point out, compute and network are but one part of the infrastructure equation for stateful apps, one which Fly is adept at. Fly's database story will only improve with time (and I believe they are already looking to partner with other database SaaS vendors), but till then, read-replicas are a pretty resourceful solution. What Fly really excels at is the dev-ex of deploying apps globally (they don't really compete with VPS providers, that's a different market, imo). There's no mucking around with deployment, orchestration, configuration (and to an extent monitoring) to distribute apps over Fly's infrastructure. > If you have let's say 6 instances spread across the globe with 1 dedicated CPU + 2 GB of memory each that's $31 x 6 ($186) just for your apps. Agree. They need to work on their pricing tiers. It is a steep jump from $2/mo with 256M RAM + 0.05vCPU (?) to $31/mo for 1vCPU + 2G RAM.
- lclarkmichalek 5y agoThere are an incredible number of websites that have incredible read:write ratios. I would suggest doing everything you can to avoid writing to the database on every request.
- jrochkind1 5y agoI wonder, of those websites with incredible read:write ratios, how many have the read-only requests pretty cacheable at CDN level.
- mrkurt 5y agoNot many. I worked on Ars Technica back in the day, it's the most CDN-like workload you can imagine. We couldn't ship features we thought were valuable, though, because the CDN was in the way. CDNs have gotten better, and you can write an app in JavaScript to sit in front of your Rails app to make things more dynamic if you want. I believe most devs are better off running their fullstack app where they need it and skipping the additional infrastructure layer. CDNs are an architectural misfeature that only exist because Fly.io wasn't around 20 years ago. I'm being extreme, but I think that's fundamentally true. ;)
- pbowyer 5y ago> CDNs are an architectural misfeature that only exist because Fly.io wasn't around 20 years ago. I'm being extreme, but I think that's fundamentally true. ;) Spicy take :) Although building for a dynamic CDN (I'm thinking Varnish here) feels like building inside-out, I can't see a way to deliver pageviews as efficiently (in terms of CPU or Watts per view) without using a CDN and a lot of caching. With Fly I guess you flip the architecture around and run code but cache a lot of partials that you assemble together. Nicer than working with ESI and its "cache it all but punch holes in the page and render those bits again" approach, but does the efficiency hold up? My architectural misfeature would be ESI [1,2]. So useful and so painful to use. And that's before we get to varying support in different proxies and caches... 1. https://www.mnot.net/blog/2011/10/21/why_esi_is_still_important_and_how_to_make_it_better https://www.mnot.net/blog/2011/10/21/why_esi_is_still_import... 2. https://twitter.com/peterbowyer/status/1366324396026118149 https://twitter.com/peterbowyer/status/1366324396026118149
- sam0x17 5y agoJust a note that people interested in this solution should really take a look at Ruby on Jets as it lets you run an essentially standard, drop-in replacement for Rails on lambda, and the performance seems to be better as well in terms of time to first byte, request latency, etc. We have a 0.995 appdex score running 100% on Jets. Right now we are single region but this could easily be set up in AWS to exist in every AWS edge location and use latency based routing to map to the proper API gateway. Database-wise you're free to tackle that how you like -- no limitations on that end.
- samwillis 5y agoI think the thing is, for most people they won't need to do the global distribution that Fly.io is pioneering, what they want is a better cheaper Heroku. Fly.io is already exactly that too. For the 1% of people who do need that global distribution, what Fly.io have built is incredible. I currently host on Heroku and plan to switch to Fly.io once they have an equivalent to Heroku Postgres's WAL point in time restore.
- sealeck 5y agoI think that a lot of people don't do global distribution by default, and thus miss out of many customers from countries that aren't close to one of their datacentres. But they don't realise this (how can they - they have no data on what might be) and thus think that they don't "need" global distribution because in their current world, they're fine.
- samwillis 5y agoYou are quite right, and Fly.io can be that "gateway drug" to taking advantage of it. I suspect that is also their exact business model too, attract customers when they are small and run in one region, then as they grow encourage global distribution extracting business from them. My business doesn't "need" global distribution but it could defiantly be argued that it could "benefit from" being so.
- onphonenow 5y agoIt can also be harmed - GDPR is not easy to comply with / stay on top of as an example
- welterde 5y agoIf the site doesn't make many requests in order to work (like for instance HN) then you can also use it just fine despite being very far away from their DC. And by optimizing for few requests and small size, you also get the additional benefit that it will work nicer if the user has a bad internet connection!
- 5y ago
- deleted 5y ago[deleted]
- JOnAgain 5y agoI appreciate that they have made globally deploying a rails app, Postgresdb, cdn, network routing fast and easy. There is always lot of finicky configuration issues and it takes a lot of time to get this all set up right. Like lots of IaaS, they are making something hard easier. They are not, though, removing the need to build your app to this paradigm. The conventions and restrictions you need to follow to realize the benefits remain and are similar to what you’d have to do yourself. So they’ve cleaned up lots of application and deployment gunk, but the app engineering work remains. This is progress. Very nice.
- ertucetin 5y agoWhen to support JVM languages?
- sudhirj 5y agoFly just runs container images, so you can already run any language you want, including the JVM.
- onphonenow 5y agoThey don’t do enough in my view to sell the basic story here. So it’s non obvious
- mrkurt 5y agoWe added this yesterday! https://fly.io/docs/getting-started/dockerfile/ https://fly.io/docs/getting-started/dockerfile/ It's getting less non-obvious, I hope.
- robgough 5y agoI'm really interested in fly.io after their Postgres post the other day, but I've not seen anywhere what their recommended solution is for ActiveStorage – is it still writing to S3 (or equivalent), or would it be somehow using their volumes? Are there any published examples (blog posts etc)?
- remorses 5y agoUsing volumes as some sort of s3 would require you to basically build s3 from scratch, you would still need to create an auth system, a server to handle uploads, a way to manage uploaded content maintaining their content type somehow (maybe using another db), a static server, .etc
- klohto 5y agoNobody's stopping you from running MinIO on top.
- klohto 5y agoActiveStorage has a local disk support, right? If you do need an S3 compatible storage on edge, you could deploy MinIO[0] [0] - https://fly.io/docs/app-guides/minio/ https://fly.io/docs/app-guides/minio/
- mrkurt 5y agoS3 or the equivalent is best, yes.
- acejam 5y agoCheck out Filebase [0]. It's powered by Web3 technologies including decentralized and distributed storage networks, effectively creating one giant "global" S3 region. You could almost think of it as the storage-equivalent to Fly.io. It also works with ActiveStorage out of the box since Filebase has an S3 compatible API. [0] https://filebase.com/ https://filebase.com/
- deleted 5y ago[deleted]
- damagednoob 5y agoMaybe I missed this in the link but I didn't see how one of the common problems in a distributed application is addressed: * A POST request is redirected to the primary data source, the resource is created and the id is returned * A GET request is immediately issued for that id but the resource that has not been replicated to the regional data source * :boom:
- mrkurt 5y agoOur Rails gem pins requests to the primary region until the data is replicated. We talk about this more here: https://fly.io/blog/globally-distributed-postgres/ https://fly.io/blog/globally-distributed-postgres/
- allknowingfrog 5y agoThe article touches on this "create-and-redirect-to-show" pattern at the end of the "It's not actually magic" section. https://fly.io/blog/run-ordinary-rails-apps-globally/#it-s-not-actually-magic https://fly.io/blog/run-ordinary-rails-apps-globally/#it-s-n...
- Dave3of5 5y agoI wonder what the costs are to run something like this for a real world app. Fly.io charge outbound bandwidth fees. You've got instance / volume costs for all the regions for the DB and app servers. IP addresses are charged. Can someone try it for a medium sized app and send through their monthly bill, that'd be great thanks :).
- t_christensen 5y agoI deployed a little side-project (https://thecitymapquiz.com https://thecitymapquiz.com) to fly.io yesterday. The deployment went really smooth, but friends testing it out complained their connection (websockets in Phoenix LiveView) dropped. It might be because its running on the cheapest VMs, I don't know yet. That said, it was really satisfying seeing the application running in Seattle, Hong Kong, and Amsterdam within minutes after launch.
- mrkurt 5y agoThis is probably a websockets bug that crops up during deploys – the connection breaks and reconnects keep getting sent to the now-gone VM for >60s. We're furiously rebuilding our service discovery plumbing because it's slow to propagate. I'm hoping we have the websockets issue fixed this week.
- t_christensen 5y agoSounds good. But I probably should implement something to store the state between websocket connections anyways. Loosing all progress when a connection drops is probably not optimal :-)
- KuiN 5y agoA bit off topic, but your game's brilliant fun. Just did the worldwide one, got a semi-respectable 23/34. Funny how easy it is to identify North American cities vs European ones. Will definitely share with some friends, great work!
- t_christensen 5y agoThank you. I think 23 is pretty good - I have looked a lot on these maps during development and I only managed 24 after I deployed the site yesterday. I'm not really satisfied with the site yet, but I through it was time to find out if any other than me found it interesting - now there is at least one other than me :)
- mattbee 5y agoIf this global replicated architecture is now a nice, polished, improving hosting product - how come so many well-funded global brands don't appear to benefit from an architecture like it? Like Airbnb taking many seconds to load many parts of their app from the UK, or business apps like Xero which respond tens of times slower than a local app from 30 years ago. Surely these are the sorts of companies which should be on top of global hosting, now that a hosting firm can box and sell it?
- jgalt212 5y agoWhy do you need all these regions? Is there any real money to be made outside of G7 that will be greatly decreased due to increased latency?
- Lio 5y agoThat's a good question but not one you could answer easily without proper research into your chosen market. If I was to speculate though I think you'd possibly find that you have long tail of potential customers spread outside of the G7 countries. That's leaving out that there are a lot of very wealthy non-G7 countries.
- atonse 5y agoTo me the real key here is making multi-datacenter instances easy, whether those are multiple datacenters in the same country or 37 countries. But even to stick to your question, the G7 spans probably a dozen time zones. Even if you stuck there, you'd still have a pain with a multi-region app and see benefits.
- rco8786 5y agoFly.io continues to impress me with their pragmatic and clever approaches to otherwise challenging problems.
- pupdogg 5y agoSo you're saying that I can run my "ordinary" Rails-2.3.18/Ruby-1.9.3 app as well?
- Jamie9912 5y agoI'm struggling to deploy a basic docker application, that works fine on my machine, it handles https traffic by its self, so the Fly.io docs say to exclude services.ports in fly.toml and TCP will be passed-on as-is, but unfortunately it seems to still be messing with my TCP traffic, maybe because it's on a non-standard port
- mrkurt 5y agoYou'll need [services] to accept public TCP traffic, just set `handlers = []` to turn off our TLS and HTTP layers. We do run a proxy so we definitely mess with your TCP traffic! You can enable PROXY protocol to get some of the original connection info (ip, port, etc): https://fly.io/docs/reference/services/#proxy-protocol https://fly.io/docs/reference/services/#proxy-protocol
- Jamie9912 5y agoYup i've tried that but sadly the curl command that works on my machine fails with `curl: (35) error:0A000126:SSL routines::unexpected eof while reading` on fly.io Locally I run with docker run -p 8888:8888, so I assume the correct thing to do when deploying on fly is to build the image with EXPOSE 8888 in the docker file, and set the service internal_port = 8888 in fly.toml. Have I assumed this correctly?
- mrkurt 5y agoYou do need the internal_port, you don't need `EXPOSE` though. Will you post your config file at https://community.fly.io https://community.fly.io so we can have a closer look?
- anothersullivan 5y agoI deployed my company website / blog with fly.io It's a simple phoenix app w/o a DB, and it was trivially easy to set up. After having used K8S for Rails and Phoenix hosting before, their product is definitely something to keep in mind.
- _ben_ 5y agoWe're building PolyScale.ai[1] that solves the global latency challenges for apps using caching. Clearly that is a different proposition/architecture to database read-replicas, but if the use case is a fit, it's a powerful solution to a hard problem. PolyScale plugs into your existing database and maintains your transactionality and consistency (we automatically invalidate globally). DML queries pass through to the origin db and reads (SELECT’s, SHOW’s) get cached locally at the edge. We move the database data and query compute closer to the end user for consistent 1ms query execution times at scale. It intelligently manages the cache for every individual SQL query so no configuration is needed, unless of course you want to set manual TTL’s. 1. https://www.polyscale.ai/ https://www.polyscale.ai/
- sharps_xp 5y agoCan anyone speak to using a rails app to reach global users using fastly's surrogate tags or cloudflare's cache tags (Enterprise only)? After reading the OP, the tradeoffs seems more complex than a single origin in us-east and having CDNs cache HTML pages. The most appealing advantage I see with running rails at all these regions is you can authenticate users really quickly and redirect them to a html page in a CDN.
- mrkurt 5y agoBefore we built Fly, I spent a huge amount of time trying to bend CDNs to my will. Fastly's surrogate keys are pretty good _if_ you define a good HTTP cache schema and if every request is worth caching. My general takeaway was that HTTP is a terrible interface for "programming" things. Worse, the whole stack was difficult to test and inflexible to iterate on. And the apps I've found myself wanting to build lately rarely serve the same HTML twice. You may find differently, but I strongly believe "just run your app and DB, no other layers" is the simplest possible way to do most full stack work.
- sharps_xp 5y agoYour response got me to really look at fly... i have to try it now. After reading the free postgres and last mile redis blog post, i realized something... I can use probably the most under-used cache stores rails provides: the file_store, which is twice as fast as trying to read from a memcache/redis process. This was not even an option on heroku b/c of the ephemeral file system.
- toolslite 5y ago[dead]