Update: I had a lot of people contact me about this post and say something to the effect of, “I’ve tried outsourcing. I will never, ever do it again,” so I thought it might be pertinent to add play-by-play updates of the progress of my current project at the end of this post so you can see, in a bit more detail, just how frustrating and difficult this can be.
I’m often asked about outsourcing design or development work overseas. I’ve actually had a recent prospect balk at a proposal because he got a quote from some random overseas contractor for a fifth of what I quoted them. I don’t blame him, it’s an intriguing option for sure. You can hire what seems like a capable contractor overseas for a fraction of the cost of someone based in the United States.
The title of this post is about outsourcing development, because that’s what this story is about. In reality, outsourcing anything is a terrible idea; design, development, whatever, and I’m going to explain why with a story about a project I’m currently working on.
First of all, let me make something clear: We never, under any circumstances, outsource client work overseas. Why? Because, as this post will explain, there’s about a 90% chance that the project will either not get done right or take far too long to complete and require far too much of our time to manage.
That said, we do occasionally outsource simple in-house projects overseas, although, that will probably end very soon as well.
On with the story…
We use Toggl for time tracking and Cashboard for invoicing. The problem with using two different systems is that they don’t speak to each other. At the end of each month, we have to manually transfer the time from Toggl to Cashboard.
I don’t like manual work, especially if it’s a simple, repeatable task that can be automated. Not because it’s time consuming, although that’s certainly part of it, but because the opportunity for error tends to be significantly higher when you have people involved in the process.
Transferring time from one app to another is a relatively simple task that I thought could be easily automated, so I posted the job on oDesk, found an overseas developer with very high ratings, and hired him. I would never hire a contractor with less than 100 hours and anything less than a 4.5 out of 5 star rating. This guy met both criteria.
I then set up dummy Toggl and Cashboard accounts so the developer could develop and test the script.
Reason #1 why outsourcing web work is a terrible idea:
Unless you’re a web designer or developer, you can’t possibly think of all the potential problems that will crop up, and your developer won’t tell you about them.
Since I have a programming background, and could write this script myself if I had the time, I knew there was a major hurdle we needed to jump to get this project done right.
What if the script fails to run at some point? Maybe the Toggl or Cashboard API is down or maybe the server where the script is hosted goes down. If the script isn’t very smart, we then have the potential for time entries to either a) not get transferred at all, or b) get transferred multiple times. Neither of these scenarios is ok, so there would have to be some safeguards in place to ensure the script handles these situations gracefully.
I determined that the best route would be to use a database. That way we could store information about when the last run was, what happened during the last run, as well as a list of all time entries from each platform and whether they were properly transferred or not.
The developer was not originally going to do this. I had to specifically ask how this should be handled and recommend we use a database and some error logic to handle such conditions. This would make or break a project like this and if I didn’t have a development background there’s simply no way I would have thought about this.
Reason #2 why outsourcing web work is a terrible idea:
There are extreme cultural differences that result in a huge gap between how other cultures work and how you might expect them to work. Communication problems, misunderstandings, and rework is the norm, not the exception. If you outsource to a culture closer to ours, like Russia, you might have better luck with this, but you’ll pay more and you might still have issues.
This is where we ran into a few other issues.
First, the developer either didn’t understand or decided to ignore my instructions to use the dummy accounts I set up and, instead, set up and used his own accounts. He then sent me a link to review the script with no information on how to access his Toggl or Cashboard accounts to ensure time was being transferred correctly. He supplied the login after I requested it and I was then able to test everything.
Second, when I was able to test the script, it clearly wasn’t working properly. I said it wasn’t working. He said he found a bug and fixed it. I tested it exactly as outlined in the original project description, and it failed the tests. I said it wasn’t working. He said he found a bug and fixed it. We repeated this process 4 separate times.
Finally, he was certain it was working. He even sent a screenshot of the time logged in Cashboard.
So, I login to Cashboard and I find the items in the screenshot. The problem? They weren’t time entries. They clearly weren’t time entries. Cashboard has a section devoted to time entries with a button that clearly allows you to “view all.” There were no time entries there. The items he logged were saved as tasks, with the title of the task being the total number of seconds logged.
Let me clarify that because it bears repeating. The spec said that time entries from Toggl should be saved as time entries in Cashboard under a client and project of the same name. Simple right?
What I got was a script that took time entries from Toggl and saved them as tasks in Cashboard, with the task name being the total number of seconds for the time entry.
Under no situation would this method make sense. In no universe would it make sense to do it this way. Clearly the developer didn’t understand something or I didn’t explain something clearly. And it was so painfully obvious to me, but he never sent a single question to clarify.
The project is still ongoing, and as of today, we have some basic logic in place, but the vast majority of this script is unfinished. Here are some stats that might put this into perspective:
- I personally have 10.5 hours into this project so far. Important note: This is a simple script and I could have completed the entire thing myself in that amount of time.
- We’ve been working on this project for 4 weeks.
- I estimate we’re about 20% complete.
- Based on the complexity of the script, I’d estimate I could have hired a US-based contractor to do this for roughly $1,000.
- I’m paying $300 to this overseas developer.
Even though we’re only at 20%, let’s assume we’ve got most of the miscommunication and mistakes out of the way and it’ll require another 10.5 hours of my time to complete. By the end of the project…
- I will have spent 21 hours on this. We bill anywhere from $100 – $150 / hour (let’s call it $100 for simplicity’s sake).
- I’ll have paid $300 to the developer.
- Outsourcing = $2100 in time + $300 in cost = $2400.
- I could have paid about $1,000 to have it done in the US and maybe spent 3 hours managing the project.
- Insource = $300 in time + 1,000 in cost = $1300.
- Total loss due to outsourcing: $1,100.
Ok, so $100/hr might be high because we’re calculating opportunity cost here. Maybe you don’t earn $100/hour or maybe your opportunity costs just aren’t that high. How about $50 / hour then:
- Outsourcing = $1050 in time + $300 in cost = $1350.
- Insourcing still equals $1300.
- I still have a $50 loss due to outsourcing.
What’s more is I’m managing this project. I’ve been writing code for 10 years. I’ve outsourced 30+ projects overseas. I have hundreds of hours of experience managing contractors and employees, both overseas and domestic.
Now imagine if you didn’t have the knowledge and experience to foresee potential problems or write an incredibly detailed spec along with step-by-step instructions for testing? In that case the likelihood of failure would be closer to 100%.
I know 5-10 people who have tried to outsource development projects in the past. Every single one of them, every single one, were incredibly unhappy with the process. Most didn’t even get a workable product in the end.
If I thought a client was really smart and really diligent, I used to recommend, if there was absolutely no other option, that they give overseas outsourcing a try. After seeing even these smart, diligent, hard working clients try and fail, I can’t responsibly recommend outsourcing anymore.
Reason #3 why outsourcing web work is a terrible idea:
Because even a guy who’s done web design, development, and marketing for a living for 7 years, has 10 years programming experience, and 5+ years managing employees and contractors couldn’t make it worthwhile.
We’ve all seen commercials about getting a website and “getting found” (whatever that means) for only $9.95 a month. We see ads for freelancing sites and read about how others have saved hundreds or thousands of dollars outsourcing development work.
At first glance it all sounds great. It also sounds reasonable. Why can’t someone in India get it done well for a fraction of the price? There are surely competent developers over there and their cost of living is so much lower.
In practice, however, it simply doesn’t work and if you value your time and you value your business, the risk is just far too great.
I, for one, will be doing everything in-house or hiring US-based contractors from now on.
Play by play updates for the above project
Update Feb 6, 2014:
- Sent the developer a message explaining that the time entries need combined and stored as a single time entry in Cashboard.
- Received a response about 1 day later that it was working and to test it again.
- Tested it and it is now transferring time entries successfully, however, the time for only one of two test projects was actually transferred over. Plus, the time that is successfully being transferred is very clearly not being transferred according to the spec.
- This is about the 6th time I’ve tested this app. All 6 times it is quite clearly not working according to spec. I’m getting fed and realize, in spite of this guy’s 4.5 /5 rating on oDesk and nothing but glowing reviews, he’s basically a code factory, pumping out code seemingly just for the sake of pumping out code. I’m considering just cutting my losses and moving on, but then decided I could update this post as things are happening to help out anyone who is still seriously considering outsourcing dev work.
- I decide I need to write step-by-step instructions on how to test this thing and tell him not to send it back to me until all the tests pass. The following is what I send him:
Create the Toggl entries:
- Delete all projects and all time entries in both Toggl and Cashboard to start from the beginning.
- Create one Client in Toggl called Client 1
- Create one project in Toggl called Project 1 and assign that to Client 1
- Create a second Client in Toggl called Client 2
- Create a second project in Toggl called Project 2 and assign that to Client 2
- Create a billable time entry on 12/13/2013 for 23 minutes in Toggl for Client 1, Project 1.
- Create a non-billable time entry on 12/23/2013 for 189 minutes in Toggl for Client 1, Project 1.
- Create a billable time entry on 12/20/2013 for 33 minutes in Toggl for Client 2, Project 2.
- Create a non-billable time entry on 12/24/2013 for 42 minutes in Toggl for Client 2, Project 2.
- Create a billable time entry on 01/13/2014 for 89 minutes in Toggl for Client 1, Project 1.
- Create a non-billable time entry on 01/23/2014 for 133 minutes in Toggl for Client 1, Project 1.
- Create a billable time entry on 01/20/2014 for 75 minutes in Toggl for Client 2, Project 2.
- Create a non-billable time entry on 01/24/2014 for 541 minutes in Toggl for Client 2, Project 2.
- Create a billable time entry on 02/02/2014 for 123 minutes in Toggl for Client 1, Project 1.
I’ve attached a spreadsheet with all the time entries you should enter in Toggl.
Create the clients and projects in Cashboard:
- Create one client in cashboard called Client 1
- Create another client in cashboard called Client 2
- Create a third client in Cashboard called Client 3
- Create a project in cashboard called Project 1 and assign that to Client 1
- Create another project in cashboard called Project 2 and assign that to Client 2
- Create another project in cashboard called Project 2 and assign that to Client 3
Check the results:
- Run the script
- You should end up with the following time entries in Cashboard:
- Client 1, Project 1 – 12/31/2013 – 0.4 hrs
- Client 1, Project 1 – 01/31/2014 – 1.5 hrs
- Client 2, Project 2 – 12/31/2013 – 0.6 hrs
- Client 2, Project 2 – 01/31/2014 – 1.3 hrs
- Client 3, Project 2 should have no time logged.
- Run the script again.
- You should not have any additional time entries after the script runs the second time.
Update: Feb 7, 2014
- I get a response less than 12 hours after sending the above test steps. I knew it wasn’t going to be good.
- Dev says he modified my requirements (without telling me) and the script now runs on the last day of the month.
- He also says you cannot access previous month’s data from the Toggl API and that’s why they changed the functionality (without telling me). This is simply not true.
- I remind him that his implementation won’t meet my requirements, because, aside from directly violating the spec, if the script fails to run on the last day of the month for whatever reason (maybe the Toggl API is down), his current implementation won’t ever get those time entries transferred.
- I remind him this is the reason I suggested using a database, which he agreed to, but now I’m not convinced the script is using a database. I remind him it should.
- I say the script should be modified so that all tests pass as I sent in my previous message and that I can’t budge on that – those tests are the only way to ensure the script is meeting my spec.
Update: Feb 8, 2014
- Just noticed the Toggl API key is different for every user. Not sure if it’ll be able to pull time for all users or will only pull time for the one user. Developer hasn’t ever mentioned this. Need to ask him about this but I suspect it hasn’t been considered.
Update: Feb 11, 2014
- Got a message from dev saying it’s almost working. My tests were designed so that there would be 2 projects with the same name under 2 different clients. The script should be able to differentiate based on the client – I feel like this is fairly obvious. Dev said that was not my original requirement but it’s not unreasonable at all to assume 2 projects for 2 different clients could have the same name, so I responded and said it needs to handle that.
- Looking through the Toggl API docs, I noticed that the time entry API will only pull the most recent 1000 entries, and only for the user who’s API is given. In order to ensure you get all time entries you need to use the reporting API, which will also give all time entries if you use a manager’s API. So that will solve both my issues but I’m not sure the dev knows this so I emailed him.
- I’ve got another API integration and since this will be my last time outsourcing this, I started writing it myself last night. Took me 4 hours to write about a third of it. Definitely should have just written this thing myself.
Update: Feb 14, 2014
- I’ve decided to cancel this project. I’m out 30% of the cost that I paid up front, but at this point it’s not worth moving forward. In fact, as far as I can tell, little has changed from the last iteration.
- Even after sending detailed, step-by-step test instructions, it’s still not working properly.
- Times don’t add up to the correct amounts.
- If you run the script twice in a row, all the time entries get duplicated.
- The time entries are saved on the day the script is run, not the last day of the previous month.
- I wrote the entire thing myself over the last week and it took 8 hours.
- So far I have 11.5 hours just managing this project. I actually lost time outsourcing it over just doing it myself.