How concerned should I be about a surprise bill?

I have a hobby portfolio site on the free tier and really enjoy how easy the platform is to develop on. I’m running Django connected to an S3 bucket for media files, and so far my bill is $0/month and everything just works.

However, there are many stories on sites like Hacker News of people getting burned with huge surprise AWS bills, and similar discussions from those hesitant to try fly.io for the same reason.

These stories have me spooked enough to wonder if I’m one typo away from fly sending me a massive bill. As a non-business, I’d almost rather pay a guaranteed $10/month than $0/month with an unlimited cap.

Are these horror stories common or am I just being paranoid?

2 Likes

The simplest option if you are concerned about billing is to use prepaid credits:

So e.g buy $10 of credit.

You can greatly limit even the potential for costs by not using e.g auto-scaling. With Fly, by default that is turned off. So if you only create e.g 1 vm, that is all the compute capacity you can be billed for. If it were to get a billion requests, it will simply not be able to respond. Your site/app would be down as a result, but you would not be billed for more compute than that 1 vm. As that is all you have :slight_smile:.

Since one of the things that causes large AWS bills is using their auto-scaling options which happily increase compute based on load (whether using EC2 instances, or serverless Lambda). As they provide you basically infinite computing power (which some large companies need) and the only way you can really know about it is with billing alerts. By which time it is too late. And yes, there have been some horror stories!

The other potential for a big surprise bill is bandwidth. The good news is that Fly’s bandwidth is much cheaper than AWS’s bandwidth. So the cost risk is lower already. But as you mention media files, that would be my concern. Since if you are serving e.g video files and know they are big, if they get linked somewhere popular, that could easily result in a large bandwidth bill. I don’t know what setup you have (such as whether the media files are cached from S3, streamed etc) but I’d focus on that. Optimise cache headers, maybe use a free CDN such as Cloudflare to offload requests (they don’t allow streamed video … not sure what Fly’s policy is regarding that). What you would want to be avoiding is lots of requests being served from S3. Because you pay per request and also per GB and that can certainly get expensive, fast. I read a horror story recently about AWS Cloudfront (the AWS CDN in front of S3). In that case, AWS were good enough to refund the user for the enormous cost but you can’t rely on that.

7 Likes

Thanks @greg. That’s a nice overview of the gotchas. I have autoscaling off and am only storing small images files in S3. The files themselves are served through Cloudfront. I keep forgetting about the ability to purchase credits and will probably do that for some insurance.

I realize it’s a PaaS trope to worry about the monstrous surprise bill, but as a hobbyist there’s always a non-zero chance of making a dumb misconfiguration somewhere. I became interested in fly because it abstracts away a ton of devops and sysadmin hassle and made deploying a toy site really easy. Autoscaling is of little use to me but also the one thing that makes me nervous.

3 Likes

It’s an entirely reasonable concern. It’s very easy to run up a huge bill with AWS. Weird how they make it so easy to do that! :thinking:

Image files are less of a worry than videos. However it is worth being aware that AWS Cloudfront charges per request, in addition to bandwidth. It’s not much but those dollars can also add up on a popular site. You could perhaps use a CDN that does not charge per request like Cloudflare or Stackpath, or even move that part inside Fly too (e.g Appkata: MinIO - S3 Compatible Storage · Fly Docs)

1 Like

@greg mentioned a lot of great things to think about, and it sounds like you’ve set things up to keep costs fairly predictable and contained.

If it’s at all reassuring, we’ve been known to refund the odd surprise bill. It doesn’t happen much, but we’re not really interested in making money from some misconfiguration that accidentally generated a bunch of unexpected usage. If it ever comes up, let us know so we can help you out!

6 Likes

(Sorry to resurrect a slightly old thread!)

I’ve come to ask basically the same question, but actually I’m wondering if there’s any way to make it so that services will just stop instead of my getting billed beyond a certain point. The dashboard says “Payment Method: Charged automatically” which would seem to imply that there’s a way to make it act differently, but I can’t see how to do that?

Cheers

2 Likes

no worries-- it can be helpful sometimes to have related questions nearby :slightly_smiling_face:

If you’re worried about billing and would like to set a spending limit, we can help out with this. You can add some prepaid credit to your organization (prepaid credit can be added in amounts larger than $25). Then, send us an email (billing@fly.io) so that we can set your organization up so that you won’t be charged if you exceed the amount of credit you have loaded.

5 Likes

Being a hobbyist and having no experience with cloud deployment, I would like to protect myself from unexpected costs with a prepaid credit, but I think $25 is too much just to test the platform. If I were to test 4 different platforms in this way I would spend $100 and give away $75 after choosing one of the platforms. So my request is simple: can you lower or rather eliminate the minimum amount of prepaid credit that can be purchased?

3 Likes

We’re not going to lower the minimum prepaid amount.

It’s difficult to have burst usage that grows unexpectedly on Fly.io. With the exception of bandwidth, everything we bill for requires manual provisioning.

We’re comfortable with this setup, and think it’s a good balance between helping you manage your costs and the level of engineering effort on our end. In general, we’re not going to put a lot of time into preventing you from provisioning paid resources. We’d much prefer to refund mistakes after the fact.

5 Likes

@bman wanted to point out that, although you mentioned just small image files, Cloudflare R2, which is mostly S3 compatible, might be a cheaper option than AWS S3, especially as they don’t charge for bandwidth.

1 Like

Also see: S0 aka AWS Lightsail Object Store which is fully-compatible with S3 and cheaper (but not as cheap as R2, so moving soon to it, anyway). Right now, we front S0 with Lightsail CDN and Cloudflare CDN.

1 Like

Hello!
Is there no way to set the limit for bandwidth & to stop the app when it reaches that limit?

1 Like

Hi @eli I sent an email to billing@fly.io on 1/4/2023 regarding this issue but I haven’t heard back yet.

My issue was that I added a credit card before I knew you could purchase credits. Then I purchased credits and now I’d like to remove my credit card so that its not charged beyond the $25 credit. Not sure if that is possible?

Could you please help or point me the right way?

Thanks!

1 Like

What would be nice is if Fly would make a dashboard where I can do more than just merely cap dollar amounts, where I can have one master toggle switch for everything in any “organization” I may ever run under my account, a toggle which very plainly shows and enforces that none of my projects will ever be allowed to cross over billable thresholds in the first place.

For example if suddenly one my projects is getting requests that would exceed a free bandwidth limit, I would much rather have a big blinking red button that I toggled off a month earlier that would just stop my project from running, period, and then send me an email to say "Hey, if you want to re-enable this app, you’ll need to flip that toggle switch, because now it needs more [insert billable resoruce here].

I mean it doesn’t get much more plain than that.

I honestly would hate having to manage multiple accounts just to have two hobby apps, because I wouldn’t want to add a credit card, so I could prevent surprise bills. And by two hobby apps, because of the way Fly works with Postgres, unfortunately I implicitly mean four apps, because both databases are also considered apps by Fly, even though from my own human point of view I’m literally only deploying two actual apps.

I’d be more inclined to add a credit card to enable the second hobby app (from Fly’s point of view this is the 3rd and 4th app, even though it’s not), if I knew I had a master switch that would never allow any of my hobby apps to ever exceed any free thresholds, ever, and I had to press the button with both hands for 30 seconds after re-entering my password to confirm my setting which is outlined in big bold letters.

I mean heck, it’s not even managed Postgres yet it still consumes my free app quota and necessitates adding a credit card.

@s0meb0dy I agree it would be neat but as Kurt mentions, VMs, IPs, volumes etc are manually provisioned and so as long as you don’t enable things like auto-scaling, you fix the spend per month at whatever you are comfortable with. So that leaves bandwidth and the cost to build that kill-switch vs. the benefits it would bring them.

It sounds like they feel it’s not justified and so the question is how could you implement that yourself :thinking:

I had a thought about this a while back (for a Lambda function, but the principle applies) and the solution I came up with was a proxy. If it’s general web content (HTML etc), Cloudflare is free. As long as you set your app as only being accessible by it and you set your caching correctly, Cloudflare absorbs X% of the load. In my case it wasn’t and so a paid (but super cheap) option is Bunny. You can set an edge rule that limits your pull zone to a max of XGB a month. So you could put that in front of your Fly app (Fly is the origin), set it to block requests after say 100GB (or whatever), and problem solved. That edge rule’s value is your kill-switch toggle.

You stay within Fly’s limit and pay $0.50 to Bunny (or whatever they charge). Again, you’d have to set up your app so only it has access to it: