four bean soup |
A "sneak peek" into the kitchen at four bean soup. |
four bean soup is a family business and I wanted to share something our family did to help our local community be a nicer place. People before us did things greater and lesser, big and small, that have impacted the world around us. While reflecting on what we did, I starting thinking about how to apply it to our internet communities as well.
Let’s start with what we did:
Crossroads1, our church, started a yearly effort called Go Cincinnati2 5 years ago. We’ve wanted to be more active and involved so we decided giving 4 hours of our time to help the city seemed like a good way to do it. We were assigned to help the Cincinnati Parks department beautify the Mount Storm park in Clifton.
Our group of 40-50 volunteers spent four hours laying down fresh mulch, putting fresh paint of picnic tables and benches, planting flowers, and clearing away a ton of grapevine and honeysuckle “brush”. These are tasks that would have taken the parks department weeks to complete. While it might seem small or insignificant, we were able to help the parks department accomplish normal tasks and hopefully help them focus on really important things.
The open source community is just as important as local communities. Where would we be without Vint Cerf’s efforts? What would life be like without Michael Widenius program, MySQL? I know my daily life would be much different with David Heinemeier Hansson’s release of Ruby on Rails.
Local tech communities also play an important role, as they are a good place to share and learn on tech topics.
There are so many ways to get involved in making communities a better place. So of them include:
Saying “Thank you” can also play an important role in making communities a better place. If someone is doing non-profit or open source works, sometimes a heartfelt “Thank you for open sourcing Ruby on Rails, it has really impacted my daily life by allowing me to make a great living by writing beautiful readable code to build websites” can go a long way. A small gesture can sometimes really brighten up someone’s day.
Links
Every wanted to just jump in feet first and get an app launched? We have! We’ve even done it before in the past, with railsrumble, and we tried to do it again a few weeks ago.
How did we fare? Let’s explore the goals first and then how we did.
We had an overall task list of 10 things for 2 of us to complete. We hired a babysitter to watch the kids from 10am to 6pm while we focused on working. Our major goals included:
I said this in a talk I gave about winning the Rails Rumble in 2007, knowing your tools can make a huge difference. Final Cut, Node.js, and MongoDB all had steep learning curves.
Wendy took on the task of editing the videos while I worked on the node.js tracker. In the end, it turned out to be much more of a collaboration on the video editing, as it took both of us tinkering to get things right and we still feel like n00bs. I am glad she took the lead on this, because I was having trouble wrapping my head around node.js.
Choosing node.js and mongoDB for beancounter was probably a real downfall for getting this task done, but something about node.js strikes a cord in me - it feels like the rails community circa 2004. Documentation and example code bases seem hard to come by. The MVC frameworks built around node.js are all a bit newish without many leading contenders. I am getting the hang of it thanks to @atmos.
Do the simplest thing possible and iterator on working code later. After I made the decision to move forward without beancounter for the first episode, my next order of business was to get a prototype of honeysquares up. I spent about 35 minutes writing the models/db structure/migrations and another hour getting the controllers and js all hooked up. As I deployed and played with the app I tweaked it, but it still lacks an actual UI for now.
Seeing an idea come to fruition can be a very powerful motivator, no matter how basic.
In hindsight, techniques like time boxing might have made sense when playing with new technology. We are still pretty happy with the results of our “launch week”, we finished 50% of our todo list with our small team of two!
We now have small wins to build on and we’ve cleared our plates to keep working on the new tweethopper design.
The other day I was poking around on an old server that I am getting ready to retire. I ran across some ruby scripts, the very scripts that spawned the idea that is now tweethopper.
I saw a post on 37signals blog [1] recently that talked about adding features to instapaper that only the developer needed - I couldn’t agree more. When you start adding things you don’t need or won’t use, you put much less thought into it, which can have disastrous consequences for your app.
Building something you need helps you focus on the important parts and you build something that is opinionated. These opinionated views and approaches can make your application strong and differentiate this app from others.
When I built tweethopper, I was tired of the non-scalable method of copy and pasting script files, editing them, adding them to cron, etc. I wanted a convenient way to quickly setup a new twitter account and give people the ability to have a group control the tweets. Moving from a ruby script to a rails website seemed the natural progression.
After building the first iteration of the service, we started looking at other ways we could use the tools to help our workflow. Feed tweets and Auto Follow features were added as we discovered they could help in running our business.
I recently added a feature I didn’t need to tweethopper, I had a number of users asking for custom bit.ly api key support. I hooked up all the code, added some text boxes to the forms, and launched the new feature.
A strange thing started happening after launching. People would sign up, only to cancel within a few hours. I decided to finally email someone who cancelled to ask them why they did - his response was “I don’t know anything about apis!”. Baffled, I started poking through the application. Lo and behold, it was the new bit.ly api key fields that had scared him and others off.
When you add a new feature, you test it. In my case, I wrote plenty of unit tests around these features to ensure they worked. I tested everything from terminal on my local machine. I didn’t actually use the feature in the live application because I didn’t need it.
Had I taken the time to use the new feature, I would have seen the small bug that users would run in to. When you copy/paste the bit.ly api key from their website and input it to tweethopper, and extra space comes on the end. If the space is left on, the bit.ly api won’t let you login properly. This leads to is.gd being used to shorten links instead of bit.ly in our application. A simple ruby chomp call fixed this issue right up.
Using “NO” is a very valuable tool. Being opinionated is an important method to control the function and flow of your web app. The goal isn’t to turn down every feature suggestion you get, they should be explored. Just implement the ideas that make sense and you will use yourself.
Links
So you build web apps and maybe you recently decided it’s time to strike out on your own? When deciding on a direction for a business it is important to understand what you are selling and where it’s limitations lie. There are four basic ways to bootstrap a new business:
While these all might sound like a great way to get started, you must consider the real product of each of these - how much time you spend on them to earn your money.
Contracting can be a very fun and exciting business to run, but the key thing to consider is that you are directly selling the hours you have each day. In a perfect world, you could sell 40 to 50 hours a week at $150/hour and live a great life! In the real world, you spend a ton of time doing other things such as finding and meeting potential new clients, writing proposals, closing deals, etc, etc.
Building web apps for others can be fun and offer a chance to change what you are working on week to week. One of the only ways to grow this type of business is to hire sub-contractors or employees. You can offer your workers a fraction of what you charge your clients, and free up a bit of your time in the process. If you decide hiring people might be too dicey for your startup, you will always be limited by your focused billing time.
This is a 1:1 growth model, comparing hours spent to money made.
You’ve built this great app, but you don’t know how to charge for it, so you decide to slap AdSense on the site… If you’re lucky enough, you might break 6 or 7 digit pageviews per month, which will pay for your monthly iPhone bill. Not very ideal.
Growing an ad business leaves you with two choices: hire an ad sales guy OR build a custom affiliate ad system. Either choice, you are taking money or time away from your primary focus of building a web app and spending it on finding better ways to sell your pageviews. Hiring a sales guys, even if it is commission, doubles your expenditures. Building and managing an affiliate network will consume most of the time you have for your regular web app.
This is a 2:1 growth model, comparing hours spent to money made.
Eureka! You’ve found a perfect idea and you even know how to charge monthly for it, good for you. Let’s say you spend 120 to 200 man hours getting the app ready for launch. Let’s also say you offer a plan of $5/month after a free 30 day trial. You launch and you get 10,000 uniques from your aggressive twittering and word of mouth, and convert the standard 1% to paid customers.
You’ve now set yourself up to collect $500 a month off your initial 120 to 200 hours. On top of that, with tools like twitter, facebook, podcasting, and other word of mouth; you could easily grow your business ten fold in first few months.
Server scalability and word of mouth are the two key growth points for a subscription model. Services like EC2 or Linode make it quick and easy to purchase hardware you need on the fly. Scaling really is easy with open source tools like nginx, haproxy, and mysql. As a friend of mine once told me “Server guys are like car mechanics, a dime a dozen”.
This is a 1:N growth model, comparing hours spent to money made.
Building two apps at once can be a very tricky thing, indeed. While this option may seem appealing, I will warn you it isn’t for the faint of heart. I’ve attempted this approach with a partner, and it didn’t work out in the end. I’ve also been an employee of a company that tried this model and had moderate success with it - the growth curve can be insane for the number of workers you bring in to get things going right. If things don’t feel pressured when trying this model, you’re doing it wrong ;).
Time once again is an enemy of this model, but with this approach you may have a larger talent pool to tackle time sink issues. You will likely also end up with a talented worker to help with scaling issues.
This approach can offer more stability if you can pull it off, but it is very easy to get off track and focus in one area or another with a smaller team. I often refer to this phenomenon as “streaks”, and we ran into it quite often when I attempted it with a partner. For example, let’s say you have a client deadline on Friday and you start off on client work with a bang on Monday. Tuesday you decide to focus on your company web app, making changes and trying to add new features. Next thing you know it is Thursday afternoon and your company web app is updated but you have a ton of client work still left for Friday morning!
This is a 1:M growth model, comparing hours spent to money made.
I wrote this to help people who might be starting a new business like I am, and to encourage them to take the time to really make the right choice. In the end, it doesn’t matter what you choice, you have to execute if you want to succeed. Here is a quick run down of businesses that make these models work:
We’ve been serving up incremental updates to Tweet hopper recently. A major focus of the work has been on increasing test coverage, but I wanted to give everyone an update on bug fixes and tasty new features that have been added as well.
We really love to hear from the people that use tweet hopper every day and would be ecstatic if you could give us your suggestions. We have several exciting ideas brewing, including new job types, oAuth support, and much more!
What’s going on at Tweethopper? Who is Tweethopper?
Has your account been deactivated and you’re wondering why? A month ago we sent out an email that said we would be transitioning to a paid application business model in order to have the time and money to improve this app. We got a lot of emails about this transition and thought it would be a great idea to shed some light on who we are and how this change will help.
Tweethopper is owned and operated by a family business called Four Bean Soup. When I say family business I do mean family business. There’s myself, Josh Owens, and my wife, Wendy and our 3 kids. Since our kids are ages 5, 4, and 1 they are more there for inspiration. I do all the work on Tweethopper myself and have struggled to find the time and money to keep it going. We launched this app about a year and a half ago and have been supporting in and nurturing it ourselves, hoping to make it into something that people would find enough benefit to pay for.
We welcome any suggestion you might have, and because of the feedback we’ve received we are introducing a free plan as well. I hope you will help us grow tweethopper into something amazing. In case you missed the email about switching to a paid plan the info is here.
Thanks, Josh, Wendy and the kids :)
We recently relaunched tweet hopper, as it is now owned and operated by four bean soup. The relaunch is part of our effort to build a profitable company that can sustain our family (my four beans…) while offering a great product with solid customer service.
As some of you may have noticed if you tried to sign up in the last week or so, it wasn’t working. I have one reason why: Paypal. We initially signed up for their Website Payments Pro offering, the same one we used while running my previous business, Handcrafted. After two weeks of testing, we launched and everything was going smoothly after we worked out a few bugs.
A friend of mine happen to IM me on the 18th and we chatted about getting tweet hopper launched, the Paypal setup process, and some other business related stuff. He sent me this link about a Paypal horror story and warned me to be careful about relying on Paypal. Low and behold, the very next morning I received an email at 7am from Paypal saying they suspended the account and they need more business details, on a Saturday to boot.
Not sure what to do, I logged in immediately and started sending them the docs they requested. They wanted silly things like my list of suppliers, even thought it is a purely digital service I offer. They asked for:
The timing couldn’t have been worse, we were rushing around that morning to head out to an all day Nutcracker event for my oldest daughter. I quickly got them all the docs before we left and spent the 45 minute car ride on the phone with customer service. They finally said they needed time to review all the documents, I should hear back in 24 hours.
The 24 hours came and went, so I called customer service back. They reviewed the documents on the phone with me and lifted the restrictions on the spot! I was so happy that I could put it all behind me. Then I logged in and saw the Website Payments Pro was still gone. I called customer service back again and asked about my payment processing, they said I needed to reapply for it and they got the ball rolling, but it would take another 24 hours. I waited patiently, actually thinking it would all be ok because we used Website Payments Pro at Handcrafted with no issues.
23 hours later I received an email informing me I was too high risk and my previous approval was being denied. When I called customer service they informed me the virtual terminal department doesn’t take phone calls, I would have to email them. I did, a half hour later I got the same denial letter sent back to me. When I emailed a third time they added a note saying there was nothing that could be done before parroting the denial again.
A mere two days before Christmas, we were left with no options for a gateway and we weren’t sure how to proceed. Luckily we made the decision to use Spreedly before launch and we had some options for a new gateway - namely First Data. Nathaniel from Spreedly had recommended First Data, so I gave them a call. They sent over paperwork for me to fill out, but they couldn’t start processing it until the Monday after Christmas, what a bummer!
I sent them all the info right away and waited to hear back. The whole process was slow and tedious compared to Paypal, but we finally got the approval and account setup after two weeks.
After I was up and running, I realized I need their API not their virtual terminal product. After a bunch of emails back and forth and a couple more calls to customer service, we finally had what we needed! I quickly plugged it into Spreedly and gave my credit card a live test - it worked!
I think there are three important lessons that we learned as a business:
I really can’t say enough about #3, to make the change, we didn’t modify any code. We just logged into Spreedly and added a gateway and switched all the card types to use it. Previously charged cards that were handled under paypal will now be handled under First Data for next months charges!
The other day, we took tweet hopper down for some unexpected maintenance. I just wanted to take a minute to talk about what we did and why it had to happen.
Since we changed out all our hardware when we switch from Handcrafted to Four Bean Soup, we didn’t have the need for the same shared resources as before. All our linode servers are now solely dedicated to tweet hopper, we moved from six shared servers down to three dedicated boxes.
Three servers proved to work ok, but once we got some started getting stats, it wasn’t what we were used to serving up to customers. We try to keep most page loads under 200ms and a YSlow score of 80+. We were averaging a few seconds for page loads, as you can see in this graph below.
The unexpected downtime came about because I didn’t realize how slow the service was running. I knew it wasn’t up to par with what we offered before, but I didn’t have any insight into real metrics. The morning the service went down was the morning New Relic finally released a version that supported Unicorn for stat tracking. We immediately set to work installing a dedicated mysql server and put it into service at the first real slow time in the EST time zone - usually we shoot for midnight, same this time.
The results are spot on with what we wanted out of the upgrade. Our page load times dropped to 85ms on average, with some spikes hitting 150ms. If anyone is looking for a good mysql config, we used Evan Weaver’s 512mb vps setup. We will continue to use New Relic’s rpm service to monitor and find slow spots in our app, we love it!
Recently we have been working on adding billing support to tweet hopper, and we had all types of debates on how to handle each little nuisance. After much discussion and research, I have found the right answer: don’t make it complicated!
There is a saying, “no code is faster than no code”. Very smart coding proverb, which can be easily restated as “no functionality is less buggy than no functionality”. What I am trying to say is, adding complex billing functions just adds unneeded complexity to an already tough problem.
This decision doesn’t have deep ramifications, but it is an important question to decide on. Do you bill every 30 days or the same day every month? Services like github charge on the same day every month, or be more like 37signals and charge every 30 days. The biggest difference is that going every 30 days means you get an extra payment every 10 years… Yes, 10 years, shrug.
There is also one other issue to consider if you charge on the same day every month, heard of February? What if someone signs up on the 31st? You have to start accounting for month end dates and make sure you get a monthly charge in on shorter and longer months, leading to more code complexity.
Wait? Someone wants to upgrade in the middle of the month! There are two different schools of thoughts; prorate or just bill the higher amount on the next billing date. Linode, our hosting provider, charges on the 1st of every month and then charges prorated amounts if you need to upgrade or add services. On the other hand, github and 37signals both wait and charge you the upgraded amount on your next billing date, but you get immediate access to upgraded plans.
The prorating method has another down side that can lead to extra code complexity if you aren’t careful. What happens if you charge a customer $30 a month and they signup on November 29th? If you prorate and charge them, you will charge them $1, which will be almost nothing after credit card processing fees - depending on who you use to process transactions. Linode handles this by charging prorated amounts plus the next month if it is after the 20th, but that adds to complexity.
For tweet hopper, we decided to avoid complication and skip prorating and just go with the higher billing amount on the next billing date. Why write code that has to do complicated math? The side benefit of it all? Credit card billing can be completely separated from the app and run via cron scripts, there is no need to do on the spot prorate charging.
This one is pretty straight forward for me, don’t offer refunds. Don’t write any code in your app to push refunds - your gateway should have the tools you need for the few instances that you need it. It is the customer’s responsibility to cancel their account, and if they don’t it in time it isn’t your fault.
This is a clear cut “no code” win!
Free and paid plans versus 30 day trials with paid plans, it is less of a clear cut choice. The choice really depends on your product and the resources each plan uses.
With tweet hopper we have a lot of expense that goes into even just one twitter account. Due to that expense we decided to offer a free 30 day trial instead of a completely free account. We collect the credit card up front, mark the 30 day billing date, and charge your card once that date hits unless you cancel. By offering only paid plans, the plan changing and card collecting is pretty straight forward.
37signals offers both options in their products, either free plans or paid plans, taking credit cards up front. When you upgrade from a free plan to a paid plan, they have a bit of extra logic they need to handle to setup billing dates and get the charging going.
In the end, do whatever feels right when you are collecting payments. Keep it secure and keep it simple. The most important thing to understand is that no code is less complex than no code!
First, welcome to the official blog where we talk about all things tweetbots. We wanted to take a minute to talk about the causes of the recent downtime.
Due to still unannounced changes, we had to move the mysql database and web app server to a new combined server. The mysql database was around 5 gigabytes and it proved pesky to move due to large tables with a few indexes. After the first aborted attempt on November 2nd in the early AM, we realized we needed to remove the indexes before importing 13 million row tables.
We re-ran the migration on November 3rd at 10 PM Eastern, and everything ran great! We hit a new problem when we tried to re-add the indexes to the two huge tables, they took forever, we stopped it at 8 hours. We knew we would be trimming the tables down soon, we could re-index at that point.
We let the service run all day on the 4th, but the lack of indexing was placing a heavy burden on the boxes, so we quickly put together the code to trim down our tables without causing duplicate tweets. We took the site and daemons offline around 2pm and brought them back around 6pm. We were able to trim the rows, add the indexes back, and get everything cut over to the new code on the new web server. The picture below shows both the downtime and the server load changes.

Now that everything has been changed, we are very pleased with how things are running, we haven’t had one blip since 6pm EST on November 4th, and the site is running faster than ever. Now we can get back to writing new job types!