In software development, there is often a tension between client expectations and the reality of what it takes to solve complex technical problems. As a product owner, my job is to balance the client’s short-term happiness with the long-term technical stability of the system we’re building. Here are some examples of challenges that I have encountered and how my team and I overcame them.
My role as a product owner
I am a product owner for a company that is hired by external clients to build software for their businesses. We have worked on a large spectrum of projects over the years. These have included educational websites, insurance portals, ISP customer dashboards, financial planning tools and more. The bulk of my day is spent working with the client to help translate their vision and ideas into real deliverables for the developers to build out.
In my experience, often the client does not always understand the nature of software engineering, and this is where I come in.
My role is to establish a reasonable project plan with the client so that developers have enough time to meet deadlines and build a quality product.
Aligning client expectations with realistic qualitative outcomes is way more complex than you might think. For example, it’s easy to give in and allow code quality, test coverage or proper system architecture to suffer when a budget is tight, a deadline is unreasonable or expectations are too high. A couple of months later however, the system may fall apart due to the above mentioned short cuts, which will undoubtedly upset the client. At the same time, responding with an outright “no” to client briefs means we run the risk of potentially losing out on business.We therefore have to strike a very delicate balance between managing expectations and delivering on quality.
Below, are a couple of challenges that I have encountered in the past. I will share with you what my team and I did to work around them, and what I learned along the way.
Specific challenges we’ve faced
Large scope and short deadline
On one occasion, we were hired to rebuild a website that was already live. There were thousands of users accessing it every day and about a thousand more joining every month. In addition, the website was the client’s only revenue stream so it was super critical that things didn’t go wrong.
On top of this, there were a few other key factors that contributed to the pressure we were faced with in meeting this tough deadline.
- Multiple stakeholders with conflicting opinions: For the first half of the project, we dealt with almost all the senior executives in the business. They were very much in an exploratory phase when it came to their product and everybody involved wanted to leave their mark. In addition to this, the marketing department made a lot of business decisions without consulting the rest of the company, which resulted in requirements that were very hard for us to meet.
- A third party UI/UX designer: The designer was appointed by the client, and was also located in Cape Town, but separate from our development team. Because of this disconnect, we faced long turn over times to get even the smallest change or update done.
- A distributed team with poor communication: Both our development team and the client’s base were spread across Johannesburg and Cape Town. On our side, we had poor internal communication within the team. Thinking back, I would attribute this to the high-stress of the project. Because we were under so much pressure pushing to get the job done, we often failed to follow best practices when it came to running a distributed team. The client struggled with similar problems working with their distributed teams and so, poor communication meant that we were often not on the same page.
Already faced with these difficulties, when the client decided, a couple of months into the project, that they wanted a major overhaul and redesign of their website as well as a native app for both Android and iOS, on top of the original deliverable, the developers were ready to revolt.
The scope set up by these additional designs meant no sleep for the next eight weeks: It was pretty much a rebuild from scratch within a quarter of the time. Even if we had hacked it out with no quality standard, there was no way we would meet the deadline.
As the PO, I went to the client and told them this, but to no avail: They told me that the date was fixed and non-negotiable because the marketing wheels were already set in motion. Either we did it, or they would find somebody else.
We very much wanted to keep this particular client because there was potential for a lot of great work in the future. The task felt seemingly impossible to manage.
How we solved this problem:
- I consulted my developers. In high-stress situations like this, I realised how incredibly important it is to involve your developers. They are the technical experts who know how to do the work and who are going to sit with the workload. Getting their input is key in mapping a way forward.
- We broke things down. Quite simply, we looked at what we had and what we could do with this. It’s amazing how quickly an impossible task can seem possible when you break it down into manageable chunks.
- I made it a priority to avoid an outright “no”. Instead of listing problems with the project brief, I used what I had discussed with the developers to frame each issue that we had with a solution. The client appreciated me attempting to solve problems they did not even know existed in the first place, and were more open to negotiation as a result.
This was because I didn’t just come to them with problems, I came with a plan of action.
With everyone happy, my team of developers kicked off and at the end of the day, the project was launched on time.
Pushing the right thing, even when it’s not what the client wants
Another example that came with a lot of useful learning was when we built a new section on a client’s website that involved the construction of a discussion board style component.
This discussion board allowed conversation organised around system controlled topics. The user had to be able to filter conversations around these topics, by selecting one or multiple of them and have the interface update. However, the client had an aversion for full page loads and this presented a few problems:
- Because they wanted to offer their users a slick experience, they preferred to subload content in when it was needed. This is challenging with a discussion board, as the dataset can grow significantly. The client expected to just click any of the checkboxes at random and have the interface update.
- Preloading the entire collection of data is extremely resource hungry and results in load times that would become unacceptable over time.
- The client was unhappy with the idea of an “apply” button because they had been accustomed to manipulating filters on the fly. Because we had previously built a similar feature on the same project where the amount of items to display was known and fixed, and the data could be preloaded, the client was unable to see that the current problem was a different one altogether.
The sheer amount of data that we would have to work with was what caused a real divide between client expectations and the developers being able to deliver a quality product.
I needed to find a way to communicate to the client that the problem at hand was something completely new and therefore something that we had to think about differently.
How we solved this problem:
- We looked at our working environment and reasoned about how effectively we could follow the client’s brief. Dynamically triggering a page load every time the filter changed would have worked initially because our development environments had a limited amount of testing data. However, the moment the amount of posts increased, we’d have a problem on our hands because users would complain about poor performance. This is something no one would be happy with.
- We turned to the big guns. Amazon approaches this problem by blanking out the filter component the moment a selection is made and then reloading the page. They have exactly the same problem as we were faced with: A massive amount of data that has to be reloaded every time the filter changes. The approach that they have adopted has proved to work well as customer experience has remained positive for them.
- I stood my ground and informed the client that we had no other choice. This is a common data problem and our solution was a standard solution. In situations like this, I try to remember that we are the experts and our clients come to us for our expertise. There’s already a level of implied trust there. The trick is just to be sure about yourself.
By taking the time to explain why our proposed solution would be the most effective way to deal with the problem, and demonstrating that it was something that big companies like Amazon make use of, I was able to get them to agree to try it out. We would let the feature live in the wild for a while to see if users were experiencing any difficulties with it, and then address anything that came up. This was six months ago, and no comebacks yet.
Balancing the technical solution with the client’s immediate need
On another project, we were tasked with performing a simple upgrade to a ‘Contact Us’ form for a client’s product. The client had discovered that they were getting a lot of international leads, but the contact number the user left was almost always not usable if they had omitted their country code or formatted the number poorly. The form needed to address this so that our client could easily contact these leads.
In the spirit of being agile, the initial requirements were as simple as it gets: An additional field on the form to take the dialling code, that simply gets concatenated in the back end with the rest of the number field. However, wires were crossed somewhere in the process and we were faced with a couple of problems:
- While we initially planned this simple change to only take about a week’s worth of development time, including all the testing, documentation and getting it into the production environment, an understanding of expectations seemed to get lost. Because there had been a breakdown in communication with the developer working on this change, we found ourselves two weeks in with work that was not done.
- The client, understandably, started getting unhappy. The developer, because of the poor communication, had gone completely over and beyond what was required. Instead of just providing a space to fill in the dialling code, the system would geo-locate the user, populate the dialling code automatically, show a little flag of the country selected, and even perform validation on the number format specifically for that country. The best bit was this was done for every country in the world. While the solution that was being put together was impressive, we were racking up expenses and letting our client down.
Sometimes a developer is presented with a problem that just screams for a hard-core, well architectured and over-engineered solution. In modern web-app development, the sheer amount of developer tools and frameworks available is staggering. It’s therefore perfectly understandable if a developer wants to try every new tool to solve the problem at hand.
However, we were tasked with updating the system to cater for country codes in telephone numbers. The original brief was literally this simple. The feature that we ended up with in the system went way beyond this, and we wasted a lot of resources.
How we solved this problem:
- I reflected on the role that I play in these situations. As a product owner it’s my responsibility to make sure that the amount of effort spent on a solution matches the value of the feature that we are building. When building a new feature according to a client’s requirements, I should make sure my team builds exactly what’s required, as efficiently as possible.
- I explained to my team why I think it’s best to avoid spending too much time on a new feature. We often don’t get it right the first time, and, by spending minimal effort on the problem, we make it more affordable for the client to come back and refine the solution. After the first round, we will also have a better understanding of the problem and how to solve it.
In the end, we managed to rectify the situation and provide the client with what they wanted. Because we were transparent about what had happened, the client didn’t mind the extra time we took to get the job done. In fact, they were so impressed with what the developer had produced that they began looking at how his work could help them make their product even more useful to their users.
Sidebar: Knowing your client so well that you can predict their future needs
Despite what I just said about sticking to a brief, sometimes we need to break our own rules.
No doubt as a project progresses you will start becoming more familiar with the domain of the business that you are working with. When this happens you will be able to make predictions around what direction your client might want to move in next. Don’t shy away from an opportunity like this.
As a product owner, this is exactly where your value in the project lies.
A little bit of up-front effort will go a long way towards your surprising them with your foresight.
A good example of this comes from an e-commerce project I worked on in the past. The client wanted us to build a payment plan feature for their store: The products they were selling were really expensive, and they hoped, by allowing users to pay in installments, they might draw in more of them.
We had very little time, so the feature was planned and implemented within a week. However, I knew that our client was going to want to change the terms of this payment plan eventually. So, we developed with some foresight and set up the whole system in the back-end CMS, with the ability to set up payment plans, and their associated discounts.
It did not introduce much more complexity and development time, but, a couple of weeks later when the client validated their idea and wanted to change the duration of one of the plans to see the effect, we had already handled this. We showed them the CMS side and gave them access to change these values however they wanted.
It allowed the client to hone in on their payment options, and find the best plan for their customers.
They were satisfied with how seamlessly it worked and were impressed that we understood their product so well that we could anticipate its future progression.
Tl;dr - here are some tips that I hope will be as valuable to you as they were to me when it comes to making projects work for everyone involved:
- Don’t just say no - there is always a solution to an impossible seeming problem. Come to the party with your own solutions, rather than just listing the difficulties you are experiencing.
- That said, stand up for yourself when you know you are right. Be careful about just outrightly forcing your opinion on the client. Politeness is key but back yourself when you’re sure.
- Make sure you build the right thing and not what you think is the best thing. By making an effort to really understand the domain of the project you’re working on, this will become easier. While exploring fancy technology is exciting, try not to be led astray by this as it will often give you more than what you need or want.
- Understand your client’s vision for the product. This will allow you to know what they want even before they realise it themselves. Your investedness and foresight can go a long way in impressing people and strengthening relationships.
Daniel is a product owner for a leading Johannesburg-based product development company. With about 10 years of programming experience, he is in a unique and valuable position whereby he can effortlessly translate client requirements into developer deliverables. He is very interested in the upcoming commercial space race and plans to stay alive long enough to witness the turn of the next century, because he fell asleep during the previous one and missed all the fun.