Hidden work when launching a SaaS
workshop.kwoosh.com
workshop.kwoosh.com
The trick to launching a SaaS is picking the right things to _not do_. Some of the fun of a SaaS is iterating on everything from product features to pricing to support tooling. It's very difficult to get pricing, trial periods, and billing model right on the first try. So usually you're better off doing less of that, and figuring it out later.
And you really don't need a crazy sophisticated drip email setup. Doing email marketing for existing users and new signups right is something that will get you incremental gains. If you convert 5% better when you have 1000 signups per month, you'll be happy. If you convert 5% better when you have 10 signups per month you'll never even know.
Silly as it sounds, if you spend more than an hour or two thinking about sales tax before launch, you're wasting time. Screwing up sales tax at launch will not kill you. _Skipping sales tax entirely_ at launch will not kill you. In fact, very little that can go wrong will kill you. You're probably going to die because you didn't make enough go right.
I've run engineering teams in SFBA for years and have, with a friend, built Cronitor. I've come to believe the most valuable "soft" skill in an engineer is just a relentless drive to ship, to know how to be both tactical and strategic in avoiding over-engineering.
With Cronitor, we call it the JIT Mindset: Don't actually write code until you have to, and focus on solving most impactful problems first. My co-founder wrote more about it here -- https://blog.cronitor.io/the-jit-startup-bb1a13381b0
In one sentence it's simply: Over-engineering something can be hard which can trick you into thinking it's real valuable work -- it's not. It's a trap.
It is really hard as an engineer not to complete a feature, but for a small scrappy saas product that's exactly what you have to do.
I liken it to building a bridge while your clients are walking across it. You want to be fair enough ahead that they don't fall in, but not so far you take them the wrong direction or build paths they don't go down.
What's the killer is all of the work _surrounding_ that small task.
Actually charging sales tax didn't long. More or less
if address.region in TAXABLE_REGIONS: subscription.sync()
What took the longest was developing and deciding how the screens surrounding will work. Answering things like:
- Which fields do we want to capture for an address? - How do we want to store states (or provinces, or prefectures) in a standardized way? - Is there a library that will let me select countries and prefectures? (Answer yes, pycountry is pretty great) - How do I integrate this library into my backend / front end?
In my mind it's just fit and finish. Like making the motherboard and inside of the case as beautiful as the outside. If I try and half-ass it or skip it, I'm just going to have to double back and make it right.
I do appreciate your final sentence. I'll keep that in mind going forward. :-)
There's also a benefit to integrating as many off the shelf systems to handle the product launch (stripe, paddle, etc), and slowly refactoring the ones away that may be beneficial.
Not exactly in the same vein as the others, but I've never seen soft-deletes done really well either i.e. the user can "delete" something but it still lives in the database. It's one of those features that sounds good but when it comes time to implement, it ends up being more trouble than it's worth.
One solution I’ve sometimes used is to move deleted records into a separate NoSQL database at delete-time. Keeps data around if you want to implement “see trashed/archived” later, can be migrated back in under an archived flag once you have that API, but in the meantime everyone else (including, crucially, the analytics team) can pretend that everything in the database is live. A kludge, to be sure, but sometimes a necessary one.
If you can get away with it, its much better to just delete it out, perhaps moving it into some archive table incase you change your mind later.
We actually have soft delete in Kwoosh. We’re using Django on the backend. The way we went about implementing it was with a flag on our core data-type (Apps, Screens, Discussions, Tasks etc... all share a common parent class). Then we used an custom Manager class (Django’s name for the bit that lets you set default filters for models) that sets the default filter to only show active items.
If we want to query all objects including archived items (like for viewing them as read-only) we just change our code from Task.objects.filter() to Task.all_objects.filter().
We also have another flag for controlling visibility directly. This makes it manageable to remove a parent task, hide the children tasks, and restore into the expected states.
I should write a more in depth post on this for workshop. Maybe someone would find it helpful.
I've never found it to be a problem. In fact, I find it's more of a problem to physically delete. You just have to design that way from the get go. Not added on after you've realized ppl leave.
I was the lead developer of a greenfield new b2b web application that took several months to develop the MVP for, then another almost 2 years to develop support tooling and systems for.
We would get calls that it didn't work with no other information, calls that it didn't work with "my older samsung", emails with pictures taken with another phone of the login screen with no other information, users that didn't know the name of the company they worked for, or even their username in the application.
We found suprisingly that there was a subset of our users that couldn't even tell you if they were on iOS or android! But quickly we learned that it's not their job to care about that, it's ours. We spent the next almost 2 years writing in debugging code, shipping logs back to our servers, writing code to send errors back to us to avoid having to ask the user on the phone to "please read out exactly what the error message says" only to find out that it happened to them last week and they don't remember... We wrote code to be able to "playback" what a user is doing in the app before they have a problem so we could identify UX issues, and redesigned UIs to include important information so when users sent us screenshots or pictures of the device we could get useful information from it from anywhere in the app (like app version, os version, username, company, etc...). We wrote documentation for how to enable camera permissions that they may have inadvertently denied for several android versions and flavors and iOS versions because we found that some users would be confused if the images and names were slightly different.
If you asked me today what makes our app better than all of our competitors, i'll tell you that it's hands down the "support" capability of the application, and that if a user has a problem, we can track down what they were doing when it happened and figure out a fix (either procedural or technical) sometimes before they even call the problem in!
Also, it's a sure fire way to deflate the ego of the hotshot lead developer that thinks he's made the best thing since sliced bread when the most important part of the application is a glorified log shipper!
I'd to love to hear more about how you identified UX issues from pure logging data. Do y'all write anything up about this online anywhere?
But one example of how we use logging info to clean up our UX was just kind of "watching" what the users were doing by just following absurd amounts of logging (logs like "clicked x button" are short and cheap, as long as you can filter them out when needed, they are immensely valuable). Our application does a lot of barcode scanning, and we noticed just from browsing around individual paths in our log-shipping system that if some users had an error with the camera (lowend android cameras are a lot buggier than i would have imagined!), they would go into the settings, select the option to change the scanner to a wireless laser attachment, then change it back to the camera version before going back to what they were doing.
Overall the process took them a good 15-20 seconds, and when they should be scanning about 1 carton a second in the app, that added up in both time wasted and in user frustration. We added a "retry" button to the error screen, and instantly the long workaround stopped happening. Then we took it a step further and would attempt to re-grab the camera in the background before showing the error to the users, which cut down on the number of those dialogs significantly.
It was a matter of getting an alert that this "camera not readable" error was happening commonly enough to trigger an alert, and from there was about 10 minutes of browsing the "breadcrumbs" for a few users to see the pattern, maybe an hour of adding the "retry" button in the dialog box (and testing), and another hour to do the auto-retry a few days later.
3 hours of work when it's all said and done (of course, after the timesink of developing it all), and the product is better off. And that's something that i'm almost 100% confident that we would have never found out about without this kind of logging and reporting.
We use sentry.io [0] for a lot of this error logging, and we have found it incredible at being able to "walk in the user's shoes" for things like this.
I have been pushing hard for our team to implement sentry.
I have implemented JS logging for all of our AJAX interactions, but having sentry 'coalesce' everything into a single view, as you know, is immensely useful and actionable.
For us the process started with just including the script and getting a few crashes or exceptions here and there, and once most of us were comfortable that some time investment here would pay off, we really wired it in and the benefits just skyrocketed.
Now we even have it running on our server side code in one case because it's just such a damn good tool.
I will say that the downsides are that the search is fairly poor unless you self host and have access to the database, and forget about using it for any kind of reporting over time periods (it's actually really hard to see things like "number of times this error happened in the last week").
But overall it's a very easy system to layer on top of just about anything. I know nothing about your company or product, but see if you can get the approval to spend an hour or 2 to just try it out. As long as you don't have any PII its a pretty risk-free thing to try.
https://stackoverflow.com/questions/2653626/why-are-cookies-...
They have startup pricing and we've used both. It wasn't great to pay a monthly fee, but it was far cheaper than anything I could have put together myself.
safety first. record everything.
Not needed
-> transactional emails
Most transaction email services offer same old SMTP interface.
As for transactional emails, we have found that its the planning, writing, designing, producing content for them that takes time and not the actual sending process.
I call total BS on that. Trying to shoehorn even something like Stripe into an app that has existing tables for users and companies, and ensuring it WORKS (including handling webhooks for payment confirmation, invoice generation, failed payments etc.) in less than 3 or 4 weeks is setting your developers (and accounts department) up for failure.
If you are selling an enterprise level SaaS, then things like billing history, generation of invoices for your customer's accounts department, handling lapsed subscriptions gracefully, handling changing of credit card details, giving the option of purchase orders or using other forms of payment etc. ALL have to be factored in and built before you even sign up your first customer. (Yep, we even lost a customer during the trial once because we didn't have the ability to generate a PDF invoice for them 'in app').
We winged it for quite a while with that. It was only after the billing side started to take too much time that we needed to switch to Chargebee to take away all the pain. Sure, it's manual work doing the invoices etc through Xero, but it's not impossible. It's pretty manual with enterprise customers anyway as the billing process is going to involve a bunch of back and forth with purchase orders etc.
My issue was with those who intimate that they deliberately left off any form of payment functionality, then managed to get a fully working engine up and running perfectly in a couple of weeks.
The sort of billing engine that you need to fully handle saas requirements, and especially enterprise as you say, is definitely not the sort of thing you knock up in a couple of weeks. Just ask the guys and Chargebee to find out how much work it really is. You probably couldn't even build the coupon component of it in a couple of weeks.
Having said that, integrating something like Chargebee's offering into your own product shouldn't take that long and I'd argue that if you're building a company, there are plenty of more important things to focus on before you need to even look at billing systems — Xero will get you a long way.
My point was specifically for B2B SaaS companies (especially those that operate internationally), as opposed to B2C where the requirements are a lot less stringent.
"I’ve built and sold software for the Mac and iOS. Those products all had simple billing systems. But with a SaaS, you need to handle all of that yourself. You need to handle payments, and invoices and everything inbetween."
Edit - both Spark (Laravel) and Bullet Train (Rails) will help with a bunch of this stuff:
Isn't this pretty much why companies like Stripe exist?
So, it's far from flipping a switch. There is Webhook integration, state management, notifying users, etc.
Is there an Enterprise Sales ready billing / invoicing solution? We're using Quickbooks - it leaves much to be desired.
They have also an extensive API and webhooks.
Suddenly you need to write payment abstractions on your back-end to handle both and most pre-written libraries that try to do this fail because they don't handle cases you may need.
That only handles the mechanics of accepting a payment too.
Krish, Cofounder of Chargebee here. A lot of our customers use Stripe + Chargebee combination as we complement them by leveraging the best features of Stripe. We like the way Stripe.Js, radar and auto card updater etc is beautifully built. (ex: you can pass Stripe token to create a subscription in Chargebee). We continue to build in a way that we let you use those features while providing a full fledged billing system that integrates all the way from CRM, helpdesk /intercom to accounting. Your finance or sales can collect non card, PayPal payments without any changes to the code. Enabling those business users post implementation with support is our core value prop, so that developers don't have to worry about giving internal solutions afterwards.
Give it a spin and for the idea launch stage we have a freemium tier for first $50k usd. If you have any feedback please write to me at Krish at Chargebee.
The team have always been ready to jump on a call to deal with the murkier migrations over the years — I'm looking at you, merging our single currency sites into a single multi-currency site...
It's nice to see you guys getting a lot of love in all the threads about billing on HN these days. You absolutely deserve it.
I am sharing this thread with the team. They will be thrilled to read the feedback. Cheers.
The fact that you have a freemium tier completely changes my perspective on that. Guess I didn't spend enough time looking :)
I'll check it out!
It's going well but the primary challenges we have are porting our existing data into their data model which right now uses SQL Server and some Redis. The paid version comes with descent support via their premium forum[2] but they have their own tag on StackOverflow[3]
[1] https://github.com/aspnetboilerplate/aspnetboilerplate
[2] https://forum.aspnetboilerplate.com/viewforum.php?f=5
[3] https://stackoverflow.com/questions/tagged/aspnetboilerplate...
The issue is that vendors (CRM, marketing automation, etc.) are trying to offload too much of the risk and accountability to their own end users, which leaves startups piecing together tech stacks that are sometimes not even legally compliant in their default settings. Not OK.
So, you can either be afraid and dump a lot of your money into "doing everything right" or start right away and fix shit later. I'd say don't be discouraged by the seemingly spooky EU laws.
This is not hidden work. These are decisions. In theory every part of an offering could be 3rd partied, but they will all want to be paid. at some point you have to write something yourself either so you don't have to pay someone or to do it better than what everyone else is using.
having said all of that, chargebee is pretty awesome.
Back to July 2017, when we launched PixLab[1], we opted for Paddle[2] since implementing billing, invoices, purchase orders, refunds, etc. was the last thing we want to code from scratch. We were a small team of C/C++ engineers and ML scientists with no clue on billings.
Not only Paddle did handle all the payment stack smoothly, they do also offer Paypal in the same payment modal which was a great boost for our sales since most Europeans customers prefer to use that method. One drawback is that they took 5% for each sale/subscription instead of the 2.9% that Stripe takes.
[1]: https://pixlab.io
[2]: https://paddle.com
I just start checking out when the idea of creating a cloud-hosted, multi-tenant version of our product is raised. Scale, security, liability for data protection, 24/7 operations support, billing, and metrics for billing, all this stuff we don't currently worry much, if at all about, would become first-class concerns. Unfortunately some people seem to think you just wave your cloud wand at things, and poof! everything is magical.
I feel like this might become a burden later on when you have to support multiple versions of a codebase in the wild.
Especially for Germany/Europe?
If not, why not? Sounds like a good business opportunity.
I personally used it for a couple of projects and I'm really happy about it. It probably saved me a few weeks or a couple of months of tedious work!
Workstack https://workstack.io
BrandOn https://brandon.video
I should look into Laravel Spark tho', I hadn't heard of it before and it looks like it might be just what I need.
I want to build a website with a paywall, accessible with annual subscription only. Let’s assume around 5,000 users for the first year. I assume that I can put together a WordPress website with a bunch of payment plugins - sign up, add cart, PayPal, debit card etc - would be enough.
But maybe not? What am I missing here.
Unfortunately, then you get the other 90% of the job, because you're a business and charging money, and that comes with all sorts of legal, accounting, tax and regulatory obligations that will vary depending on the place(s) you do business and the place(s) you find your customers. This is the stuff the flashy "Take your first payment in five minutes" demos on the homepages of all the payment services don't tell you about, but if you're lucky your accountant might. (If you're less lucky, you might need a more experienced accountant but won't know it, and you might wind up making expensive mistakes. Doing a lot of reading online about the rules that apply in your specific location, for example if your government's tax department offers any guides for new businesses about what they generally need to do, is the only reasonably effective solution I know to this problem.)
In practice, these things almost always come down to
(a) identifying the relevant tax rules based on your location and your customer's
(b) calculating the correct tax on sales, as well as on any payment processing fees, etc.
(c) keeping complete, accurate, systematic records of all transactions
(d) filing the necessary tax returns and/or providing the records to your accountant so they can do the serious business financial paperwork
(e) paying your taxes properly.
None of it is rocket science, it's just that it's often a big, complicated system that you have to work within, and it's full of little details like generating sequential numbering for invoices, or knowing how to handle the tax if you've issued a refund before/after the end of the tax reporting period containing the original sale, or being able to record two non-conflicting pieces of evidence to confirm which country your customer is in. It can be time-consuming and error-prone, and taking enough professional advice to understand your obligations and how to do everything correctly can be a significant expense by start-up standards.
Finally, depending on your market, you may at some (possibly quite early) point want to accept payments through more than one channel: purchase orders and payments to bank accounts, online credit cards, the various direct debit schemes or national card schemes, PayPal, and so on. If you're in that position, the "front line" payment processing services like Stripe or PayPal are unlikely to be sufficient, because it's a level above what they're designed to do. So probably you will either need to use one of the next-layer-up services such as those mentioned elsewhere in today's discussion to co-ordinate things, or you will need to do some substantial programming and database work of your own to do something intelligent about combining the functionality and record-keeping for each service.
Since all my products are #1 in their niche and I know how dirty businesses especially competitors can play, I do not use any of these bridge services!
There are concerns that these services might sell your customers' data to interested parties or at least roll their own with some insight into your pricing and market dynamics.
We started off using WHMCS. Lots of my friends who rolled their own SaaS got stuck for months changing payment gateways but we just enabled/disabled plugins a few click and kept sailing.
Customers love that we use proven/cheap solution to solve this problem and focus entirely on our app.
It was difficult, but built some good features that do give us a lot of flexibility:
* region based pricing
* region based billing cycles
* multiple plan options per region
* auto generated pricing based on live fx rates which ar
rounded “nicely” which is harder than it sounds
*% based discounts and account credit
* ability to modify seat counts
Difficulties amongst many many others are: * VAT handling (it’s different per customer type and country!) and generally having a solid grip on business finance
* abstracting it to allow multiple payment methods (stripe and PayPal)
* generalising it enough to support multiple products
* dealing with fx changes during checkout
* handling disputes, refunds, etc and their affect on product access
* just PayPal in general god damn! When dealing with b2c not including it is tempting but not really and option. PayPal and stripe in my experience give 99%+ coverage
Easy bits are the generating of invoices (prefer to do this in house) and all the other trim like emails etc. That’s just grind work.I’m proud of it though and so far we’ve done 6 figures through it and is holding up well (tens of thousands of LOC and probably around 6 months dev time). We wanted it to do a lot and the design is quite sophisticated I think.
Second payment system with meat on it I’ve written (first cleared 7 figures but is no where nearly as well designed and mainly deals with one off payments). I enjoy making them!
Would definitely of bitten off more than I could chew if I was less experienced. Making it all scalable and reliable is another layer of complexity.
One gotcha which is hard to manage on a business level when dealing with sass accepting multiple currencies is forex rates that become very out of sync with your orginal price points. Can explain more but on phone!
Still to do is adding a system for accepting POS, a lot of the difficulties we face is we sell to the whole market, consumers, businesses of sizes and education. When selling to education specifically offering native currencies is a huge competitive edge especially for sass.
Also still to do in a more elegant way is b2b enterprise customers sometimes like paying for multiple years in advance - high value orders so another important case to cater for!
ALSO still to do is create accounts for resellers to buy at discounted rates. You can see how much work is involved on this sort of thing!
Winging it with “it works” won’t cut it imo (9/10 I’m all for it!) - that is the gooiest technical debt you can take on. Imo you need to seriously invest time into a good design from day zero.
For a lot of customers even b2c a properly issued invoice is important so that does narrow down abuse.
Requiring billing address is a good catch especially for card verification although there’s a constant friction between the frictionless checkout and anti-fraud/region verification.
Main struggle we’ve had is businesses buying the wrong package - (cheaper of course)! Best way to catch this is to only issue simple receipts to the plans aimed at b2c and tell them to email invoice address if they’d like a full invoice issued.
A lot of people seem to be uncomfortable with region pricing based on abuse - however it’s important to bear in mind it doesn’t have to be 100% effective to be a net benefit. If your product is truly worldwide region pricing can be an absolute essential. As can region based billing cycles where in some cultures monthly payments are culturally the norm and annual can be hard to swallow.
Every dimension of global saas payment systems is complex. I’m tempted to say there’s startup opportunity here but it feels like there will always be a lot of glue needed and a huge amount of flexibility between customers needs so I’m not sure how plausible it will be.
Edit: worth mentioning is that EVERY saas company needs some region pricing - most simply you need to respect trade embargoes and deny all sales to specific regions as best as possible.
This is becoming a necessity since various places, notably the entire EU, now require multi-point proof of customer location for tax compliance for at least some types of sale.
It's easy to pretend you're somewhere else until you need to pay for something. Then you have the entire financial sector's anti-fraud systems to deal with, and a VPN isn't going to fool them for a moment.
Sry, that was snarky, but you really should describe your service, as I could not find out what it does.
Good point though, we could update the footer on workshop to be a bit more specific.
Yes, that's what I am referring to, the workshop-link goes to some kind of blog, but it seems to be more about tech and entrepreneurship in general.
Some kind of "About" section with screenshots would be nice.
Yes - more screenshots / a properly filled out marketing site are on the list of things to do. Good idea about an "About" section. Workshop is the name of our blog where we show / discuss Kwoosh as we build it.