Hetzner
HN user
brunosutic
I work on: https://railsbilling.com Personal website: https://brunosutic.com
Get in touch: hacker.news AT brunosutic.com
Async Ruby
I tried lnav about 7-8 years ago and as a terminal junkie I really liked the features.
The only breaking thing was a huge (almost bloated) memory consumption. At that time lnav basically just kept everything in memory. Does anyone did that change?
RailsBilling - Stripe subscriptions for Rails app in one command.
Killer feature is multiple plans per customer.
How do you guys handle past due / grace period if there are no webhooks? Like, do you notify the end-user that their card failed and they need to update their card? Or do you let Stripe send emails?
What's your approach to 3DS and related race-conditions for subscriptions? In my experience 3DS is by far the biggest problem for subscription integrations - not the webhooks.
The DX of Stripe is already great
This used to be the case back in 2015, but not anymore. The financial compliance is more strict now. You have to charge taxes. EU enforced SCA / 3DS in 2019. All of these are hard to implement (correctly) on their own - almost impossible together.
Source: I run (paid) Ruby on Rails library for Stripe subscriptions integrations. I also do billing audits. Here's an example audit where I pay $30, get ~$2000 https://www.youtube.com/watch?v=YuXp7V4nanU
Article author here - thank you for putting it this way. This is exactly the attitude I wanted to convey: it's something I tried and really liked for this specific use case. I shared because I hope it might inspire others.
"Friendly Attributes" is not the "new way", not to be used "everywhere now", does not "apply to all scenarios".
If you like it, maybe you'll use it once in the next five years when the opportunity arises.
Your input would work exactly as you wrote it if passed to `Billing::Plan.find_or_create_all_by_attrs!`, just add commas at the end of lines.
If you want to make it even shorter, you have a few options - it really just comes down to preference:
# Option 1. my personal favorite, follows structure of
# intervals and plans on a pricing page.
1.month => {red: 10, blue: 120},
1.year => {red: 120, blue: 300}
# Option 2. this is fine too
red: {1.month => 10, 1.year => 120},
blue: {1.month => 120, 1.year => 300}
# Option 3. possible and works, but hurts my brain, NOT recommended
10 => {red: 1.month},
120 => {red: 1.year, blue: 1.month},
300 => {blue: 1.year}
> there is always at least one attribute that serves as a "discriminator" between the billing plans, rightJust a note: if you try to create two plans with the same attributes, that would error because of ActiveRecord uniqueness validations (and DB constraints). No point in having multiple identical plans.
This is supported and would work with no implementation changes. The "Friendly Attributes" idea is very flexible.
Just a small Ruby syntax correction for your example:
Billing::Plan.find_or_create_all_by_attrs!(
standard: {1.month => 10, 1.year => 100},
...
)I would consider monthly Enterprise & yearly Enterprise the same plan, with modified cost & billing frequency.
How would you then call the objects that store costs and billing frequency? :)
Here's what Stripe uses:
- Product: "describes the goods or services". This is where you define a (plan) name and features.
- Price: defines the amount, currency, and (optional) billing interval. Since interval is optional, Prices can be used to define both recurring, and one-off purchases.
Technically, using Prices for recurring, and one-off payments is a brilliant idea. The problem is, no one refers to recurring payments as "prices". Everyone calls a "$50 per year" option a "plan".
That link describes billing problems of a neobank... I mean, yes, there's a big gap between my test helpers and financial institution's problems - to the point it's not related at all.
But, in principle I agree billing, even the simple SaaS stuff, is much harder than most people expect it to be in 2025. My product (linked in the original article) is based completely on Stripe Billing - and it is still very hard to avoid all the footguns.
For people wondering, I even have an example how wrong it can go: I "audited" a successful SaaS I know uses custom Stripe billing. I paid $30 for a starter plan, but was able to "upgrade" to $2k plain for free. Here's the full video: https://www.youtube.com/watch?v=YuXp7V4nanU
Hi, I'm the author of the article and the software library. I confirm I actually do use the examples from the article in my code.
Here's the example that runs in hundreds of integration tests:
expect(billing_pricing_plans).to eq billing_plans(
1.month => [:free, :premium, :pro, :enterprise],
1.year => [:free, :premium, :pro, :enterprise]
)
It asserts what plans the customers see on the pricing page.The usual response to this complaint in the Ruby/Rails community is that optimizing for nanoseconds, or even milliseconds doesn't matter when the same operation also involves multiple database queries or API calls.
Let's take this example from the article:
Billing::Plan.find_or_create_all_by_attrs!(
1.month => {standard: 10, pro: 50, enterprise: 100},
1.year => {standard: 100, pro: 500, enterprise: 1000}
)
This ensures six billing plans are created. That means 6 DB queries and 6 Stripe API queries, at a minimum.Nice to see product from Zagreb! The link is for the /login page which tells us nothing about the product. Next time post a link to your home page.
Nice work btw. The landing page is pretty and I like the pricing slider :)
We have 3 young kids in the range from 2 to 5 years old. We use white noise heavily for our kids sleep. It isolates them from the noises we make around the house.
For this purpose I recommend "LectroFan" devices. We have like 5 "LectroFan Evos" in our's and our kids' bedrooms. They just work, no apps, no upgrades, no LEDs blinking, and thank god, no screens. These devices are worth their amount in gold.
On the phone I recommend using iOS built-in white noise feature. We use it when travelling by car, and our kids sleep in their seats. When we turn the white noise on they stop talking and it quickly lulls them into sleep.
Yes, and the same feature is available on Mac too. I occasionally use it with headphones for work, when I want to stay focused.
Does anyone know if Arko can have legal troubles (like being sued) if it can be proven he "removed authorized users" from RubyCentral AWS account?
I use it for learning and play with my kids. I load the program on the board then we wire the components together and get all excited about blinking LEDs or a LCD.
The lack of features (notably Wifi on our boards) and somewhat larger size are benefits for us.
I'm glad someone is working with Async Ruby.
I like this Jeff Geerling guy.
I'm working on RailsBilling - it's a Ruby gem for fast Stripe subscriptions integrations. It allows you to implement subscriptions in your app in hours, instead of months.
You see, Stripe is very powerful, but also very complex. Coding a straightforward subscriptions implementation will take you a couple weeks at best.
That is without handling all those edge cases like: prevent starting a paid subscription without a billing card on file (yes, you read that right)!
The gem is ready, I'm currently working on getting the website up. If you're working with Rails and need a solution for subscriptions get in touch at hacker.news@railsbilling.com - I'd love to chat!
Sometimes it's not about the "edge cases" and handling Stripe quirks. The main design consideration for global Stripe integrations is SCA/3DS or "payment confirmations".
If you implement something, then add SCA/3DS "payment confirmations" later on, I think it's impossible to fix that.
I'm working on a paid Ruby gem for bespoke Stripe subscription integrations. It cuts down integration time from +6 months to less than a day, and handles many Stripe API pitfalls.
Stripe has a "developer friendly" and "easy to use" reputation. But, since 2019 the EU regulation has stepped in and made things more complex with 2nd factor authentication for payments (3DS/SCA). This made payment integrations way more complex. Integrating Stripe subscriptions now easily takes 6 man-months (I'm being very optimistic here).
Also, there are some basic scenarios that are hard to get right:
- Creating a paid subscription and ensure a customer always has a card on file (this one is almost impossible). - Upgrading a free ($0) plan to a paid one. - Upgrading paid plans, eg $10 to $100/month and ensuring immediate payment. - Guarantee customer Tax location, keep the flow simple.
I made a video analyzing Stripe integration of a successful SaaS company (+$100M valuation). I first paid $30, then upgraded to their highest $2000/month plan - for free!
https://www.youtube.com/watch?v=YuXp7V4nanU
The gem I'm working on is intended to be used with Ruby on Rails apps. It covers all the above mentioned hard cases, and irons out many more Stripe API kinks. And yes, it handles the basic-but-impossible "ensure customer always has card on file if they start paid subscription".
After buying the gem you can hand-off the task to the junior developer (it's that simple). They follow the integration tutorial: follow the steps for Stripe dashboard config, do the local env config, done.
The product (Ruby gem itself) is ready. I'm now working on the web app, tutorials etc. If anyone wants an early, guided access, please email me - contact is in the profile.
Replacing ascii with similar-looking unicode characters is an old trick. There's a bunch of these characters out there. You can use it in the code to prank your colleague developers - April 1st is nearing!
I even made a vim plugin that highlights these "dangerous" characters: https://github.com/vim-utils/vim-troll-stopper
I've never been pranked with unicode characters, but I've had a situation at work where a consultant from Japan unintentionally used some "japanese space" characters in a translation file, and that broke our app. Since I have my vim plugin running all the time it didn't take me a lot to see what's going on.
Yes, I thought you played with those apps and their proxies to get around anti-bot protection.
I also don't have anti-bot implemented right now, but that's my next step. I mean, my app "has one job" and it's not doing it well because of anti-bot protection...
Quick question: how do you handle bot protection (eg Cloudflare) with your app?
Hi HN! I'm Bruno, the founder of https://linkok.com. linkok.com is a modern broken link checker.
I got the idea before the Covid pandemic: at the time I was looking for a better senior developer job. I sent a couple dozen job applications with my resume website, and I only got a couple job interviews, and no offers. I gave up and stayed at my old job. A couple months later I was optimizing my website. I checked for broken links and the results were bad: from 12 links total, 4 were broken. That's more than 30% broken links - no wonder I couldn't find a new job!
Since then I realized broken links are a problem for pretty much every website out there. If you have a website, you likely have broken links too. And the existing solutions don't cut it. Most online broken link checkers are old, and have outdated interface. Advanced SEO tools (ahrefs, semrush etc) can do broken links checking, but are too complex and expensive for regular people.
Under the hood linkok.com crawls sites using Async Ruby, which has proven great for this type of work. I love how easy it is to work with (when compared to threads). It also made some advanced features easy, like request retries. Async is a somewhat underused in the Ruby community. If someone has more questions about it, I'd be glad to answer.
My goal for linkok.com is that it should be easy to use (think: blogger moms), and it should be accurate and powerful enough for enterprises. linkok.com is free forever for small sites (up to 100 internal pages) and charges a fee for bigger sites. It's also completely free for open source, educational and non-profit websites. This is not automated yet, reach out at bruno.sutic@linkok.com and I'll set you up.
You may find this interesting: I worked on this project for 3 years! By far the hardest part was billing - integrating with Stripe properly took me almost 1 year (Stripe is very hard). I also shaved a couple of yaks, highlights: implemented postgresql and redis high availability, I run things bare metal servers (Hetzner).
I'd love to hear your thoughts, feedback and ideas! Looking forward to your comments.
I feel like the linked article is based heavily on my own article on the same subject: https://brunosutic.com/blog/ruby-fiber-scheduler
Too bad the article doesn't contain the source reference, but oh well. I hope it gets the word out about this new cool stuff in Ruby.
Valid complaint, I'll fix that. I'm on a 13 inch screen and didn't test it on a desktop-size screen.
Fiber Scheduler Interface feature was added to Ruby 3.0 in December 2020 https://docs.ruby-lang.org/en/3.0/Fiber/SchedulerInterface.h.... Yet, the latest commit in this repo is 3 years ago.
You probably implemented your own custom scheduler implementation, right?
The app is down right now. I'm getting 502 errors