The difference between developers and product designers

Our company is bidding on the re-development of an existing product that has outgrown the technical framework on which it was originally built. The customer has received a handful of offers, and the range of costs and technologies found in those proposals is causing him considerable uncertainty in his choice.

In response to that uncertainty, we’re nudging him to look beyond whether to use Ruby on Rails (our choice), Meteor or Laravel since, at the end of the day, the success or failure of his business will not hinge on technology. Instead, we’re encouraging him to consider the difference between a developer and a product designer, and focus on the critical question of who is capable of creating a product that will ultimately prove successful to his business.

To illustrate, let’s consider what happens when you signup for an account in their existing platform. Upon first login, you see something like this:

The original specifications for this product probably contained something along the lines of, “The system will have an accounts screen that lists all colleagues associated with the organization.” The developer then went about the task of satisfying the requirements, thinking:

When the account screen is accessed, I’ll query the database for all colleagues. And to account for the case there are no colleagues, I’ll show the message, ‘No colleagues found’.

Most developers focus on requirements and technology—i.e. the database query, the message to show if the query returns nothing, etc.—and fail to reflect deeply on the actual use of the product they’re building. In this case, the developer didn’t consider the one instance—and a critical one in terms of product success—of an empty database query that every single user will experience—Their very first engagement with this screen as a new user.

As a new user in this system, I’m left disoriented and confused:

  • Where am I, and what am I supposed to do?
  • The “No colleagues found” text seems like an error message. One minute in, and I’ve already done something wrong?
  • “Show blocked colleagues?” What is a blocked colleague? If I click that, the only thing that happens is that the text changes to “Hide blocked colleague”.

Had I created this account as a potential new customer wanting to “kick-the-tires,” there’s a good chance that I’d leave and not return, since experiencing friction in my very first interaction with the product is probably a good indication of what’s to come should I stay.

A good product designer is continually putting himself or herself in the shoes of the user, taking into account their context, their mindset, their knowledge and expectations, and looking to resolve any aspects of interaction with the product which potentially introduces friction.

In this example, a good product designer would identify the need for a “blank slate” version of the account screen, that’s welcoming and orientating for first-time users. Perhaps something like:

And therein lies the enormous difference in value between the average developer, and the very few who are good product designers. The former creates collections of features that “satisfy requirements”, while the latter creates coherent, effective and ultimately successful products.

Why keeping it simple would be a better choice for TransferWise


In the world of web application development, we sometimes face technical decisions whose trade-offs extend beyond the technical. Those non-technical trade-offs can be subtle, and perhaps difficult to identify, yet critical to the business.

In this article, I want to highlight as an example my experience with the TransferWise payment system, in which technical decisions ultimately work contrary the core of the product.


In the early days of web applications, browsers like Firefox and Safari could only render web pages whose contents were structured in HTML and possibly styled with CSS. Any “logic” that formed part of the application had to be executed on the server.

Whenever you clicked a link on a screen, you’d experience a page refresh as the browser sent the request data back to the server, waited for the server to perform any necessary checks and calculations related to the request, and then your browser would display the HTML/CSS that was returned by the server.

So in those days, your browser only displayed things; any “thinking” happened on the server.

Time progressed, and browsers gained the ability to execute JavaScript software, thereby opening the door to implementing “logic” that gets executed within the browser client itself.

One of the most common first uses was in signup forms, as the browser could check that your entered-twice passwords matched, without requiring a page refresh and request to the server application.

Things got even more sophisticated when the browser could make a server request that’s transparent to the user. You’ve probably seen that when entering your username in a signup form, seeing a small spinner appear to the right, followed by a green checkbox informing you that, “Yeah, that username is still available!”

As “front-end” technologies continued to evolve over the years, we’ve gotten to the point where entire web applications are implemented in JavaScript, and run within the browser.

So, today, a fundamental decision to be taken by a developer when he or she implements a web application is:

Should I implement this logic on the server, or in the client?

The argument I want to make in this article, is that often this decision should be taken by the organization, and not simply left to designers and developers.

Context is everything

The benefit of using client-side logic is generally a smooth and seamless user experience, since the user doesn’t have to wait for page refreshes. The trade-off, however, is the risk of bugs in the user interface, since the JavaScript and rendering engines between different browser (and even different versions of the same browser!) can vary considerably.

There are some application contexts in which the risk of interface bugs is compensated by the value of a seamless and interactive user interface:

  • For example, if you’re developing a fast-paced interactive game, it could well make sense, in the interest of a smooth user experience, to implement the entire product as a client-side application.
  • Or let’s say you’re implementing product that’s likely to be used by your customers several times daily. In that case, saving a few screen refreshes might materially improve the experience when compounded daily over the period of an entire year.

At the same time, there are some application contexts in which a seamless user interface does not compensate the risk of exposing the user to interface bugs. And, here, I want to highlight an example of a company that has absolutely taken the wrong decision in this regard.

Disruption of an industry

In the past, it was terribly expensive for me to pay European contractors from my American company. First, the transfer itself would cost about $30. But then, I’d lose over 3% with respect to the market rate when the bank would convert my USD source funds to the destination currency of Euro.

TransferWise completely disrupted the market of moving and transferring money internationally, charging a fraction of what banks charge. They do this by taking advantage of volume to avoid even having to make transfers, i.e. if Customer A in the US transfers $100 to someone in Europe, and Customer B in Europe transfers the equivalent of $100 to the US, TransferWise can make the two transfers happen simply through off-setting accounting entries, using Customer A’s money to pay Customer B’s recipient, and vice versa.

What is the TransferWise product?

So what is the TransferWise “product”? If you ask me, it’s the saving of tremendous time and costs when making an international transfer.

And here’s where TransferWise have really messed up. They additionally view their “product” as the experience of making a transfer, and from a front-end technology perspective, they have decided that a slick user interface compensates the risks of exposing their user to bugs associated with the heavy use of front-end technologies.

To be specific: The process of making a transfer with TransferWise involves five steps:

  1. You specify the source and destination currencies, and the amount to be transferred.
  2. You choose who is sending the money (in case you happen to have both a personal and business profile on record).
  3. You choose a recipient from a list of existing contacts, or create a new one.
  4. You choose how you’ll get the money to TransferWise, e.g. through an ACH or wire transfer from your bank.
  5. You review the transaction, and confirm if everything looks good.

Looks simple enough, but there’s quite some logic that has to happen:

  • You have to compute the amount of the conversion from the source to destination currency, based on the current rate.
  • You have to alert the user in case that rate expires during the process of setting up the transaction (i.e. if they take too long.)
  • You potentially have to walk the user through the “new contact” workflow.
  • You have to flag the user if the chosen receipt doesn’t have address details on file.
  • You have to walk the user through the “link new bank” workflow in the case they want to do an ACH transfer with a bank that wasn’t previously associated to their account.
  • You have to exclude the ACH option if the daily limit has already been exceeded.

So the process of initiating a transfer can get surprisingly complicated.

TransferWise’s flawed decision

Well, TransferWise decided to implement the entire workflow in one single web page, in which each step in the process is contained within its own component, that opens and closes accordion style.

The consequence of this approach, as opposed to pushing all the logic and checks to the server in page refreshes, is that during the entirety of my use of TransferWise, over the past few years, I have ran into user interface bugs probably more than 50% of the time.

And sometimes we’re talking about showstoppers—i.e. bugs that, in the name of a slick user experience, actually prevent me from making a transfer!

For example, the day that the confirmation button simply wouldn’t activate. Or the day when state wasn’t tracked across components and the confirmation button didn’t provide on-click feedback, such that multiple clicks of the confirm button suddenly skipped you multiple steps ahead in the process, leading to all sorts of chaos.

Or, what happened to me today…

I use TransferWise once a month to pay my European contractors. Since the only thing that changes each month is the amount I pay to each, I could really use “payment templates”. But since those don’t exist in TransferWise, the next best thing is to click “repeat payment” on some previous transfer, and then change the amount.

But it would seem that this isn’t the intended purpose of “repeat payment”, since clicking the option takes you directly to the confirmation component of the transaction screen. You can click back into Step 1, in order to change the amount, but I suspect my particular use of this feature is what caused me to see this, when finally returning to the confirmation component:

Try what again? Going from Step 3 to Step 4? Everything looks fine. What’s the problem?!

Neither refreshing the page, nor clicking “Confirm” removes the error message or allows me to proceed As with most of these UI errors at TransferWise, it would appear that I’ve reached a dead end.

But, in this case, guess what? When I return to my accounts page, I see that the transaction was successfully processed. So the error I was shown—i.e. the one that blocked the whole process—is itself erroneous!

Again, it’s all about context

So let’s backup and think about this.

  • Once per month I need to make some transfers.
  • I use TransferWise for this because they are fast, and save me a lot of money.
  • I do not use TransferWise because their transfer creation workflow is better than my bank’s. I don’t give a shit about that. If this were something I did 12 times per day, then maybe; but this is something I do 12 times per year.

Of course, it’s not impossible to have a reliable application that’s front-end heavy. It’s just that it’s much, much easier to have a reliable application that’s not. And in the case of TransferWise, a slick front-end doesn’t contribute to the core value proposition of the product, and my own experience demonstrates that there’s definitely inadequate value compensation in unnecessarily taking the risk.


The very very last thing I want to experience in this context, are bugs that prevent me from making my transfer.

For the past year or so, each time I’ve experienced a UI bug, and have reported it to TransferWise, I’ve also take nthe opportunity to encourage them to reduce their dependence on front-end technologies, and give priority to making the process of creating a transfer as reliable as possible. But each time, missing the forest for the trees, their team have instead focused on trying to track down the particular bug I’m reporting (Have you tried that in Chrome?)

And so my hope is that through publishing this article, the larger issue might cross the radar of someone in TransferWise management, who’s in a position of considering the broader product goals.

What it’s like to take on venture capital investment

One of my favorite podcasts, recently discovered, is StartUp, by Alex Blumberg, former producer at This American Life. The podcast chronicles the story of starting Gimlet Media, Alex’s new business aimed at creating a network of story-narrative podcasts. “StartUp”, documenting their own story, is Gimlet’s first production, and what’s interesting about this podcast is that Alex records almost all of his conversations along the way, giving us uniquely inside access into the creation of their company.

Continue reading What it’s like to take on venture capital investment

Software testing and charging customers for bug fixes

In a recent update we made to a customer’s software system, a bug was discovered, which led to a discussion about (a) why the bug wasn’t caught during testing and (b) why we charge them to fix the bug.

Given our business model, this is a discussion that occurs from time to time, and so I decided to capture our viewpoint in the form of an article I can refer to as needed.

Continue reading Software testing and charging customers for bug fixes