Solution Design — A rookie’s retrospective

Alex Batrinu
Engineers @ The LEGO Group
8 min readJul 17, 2023

Webster’s dictionary defines Solution Design as…

Nah, just kidding, this isn’t a university lecture.

So, let me give everyone a bit of context: I’ve been looking to expand my skillset from just picking up a ticket and delivering it, to actively creating a top-to-bottom solution to an existing problem that needs solving.

Why?

The LinkedIn and job interview answer — I like to challenge myself.

The Alex answer — I was curious… and I like to challenge myself.

…and it also helps with career progression hee-hee.

Cool, now that the intention was there, I needed the actual work. Lucky for me, my team was looking into implementing a feature in our application — Flamingo 🦩 — which helps our Customer Services Advisors place orders for… well, customers that would call in.

Now, when an advisor starts… advising, they also start recording calls and screens for training and call quality purposes.

This is where the feature I mentioned earlier comes into place. We needed a way to pause the recordings to take payments, and then resume the recordings after the payment’s been done because, as we all know, GDPR and PCI won’t let us record any payment information.

Here’s a quick diagram of the basic interactions between the two systems:

Interactions between Flamingo and the Call Recording API

And here’s a flowchart of how Flamingo should behave:

Flowchart of decisions and cases

Seems fairly simple, right?

Well, it was a bit more complex than I imagined. First of all, we had to coordinate with another team, our very own Thunderbirds team, which dealt with the calling and recording part. Second, we needed to address the problem of how we’re going to implement this in our testing and staging environments so we don’t have to be on a call every time we want to run our app or develop in it. And third, how are we planning to make the two services communicate securely?

Well, this brings me to my first solution design top tip:

Communication

Communication is key. It is important to constantly communicate with the stakeholders, partner teams and own team members to ensure that everyone is aware of the progress being made and any issues faced. Regular status updates and demos can go a long way in ensuring that the project is on track.

My tech lead and I together with an engineer and tech lead from Thunderbirds set up a quick planning session to flesh out the basic gist of how this will all go.

I can’t stress how crucial this point is. Try and go into this meeting with a battle plan and a list of requirements and questions you might have regarding the work ahead. It will make life so much easier once the actual work starts.

We were in that meeting for a solid chunk of time, trying to figure out as much of the requirements as we could, any edge cases that could happen and how to test this.

So as a TL;DR of that meeting, and then another smaller one after — They will create the endpoints, we’ll hit them, use API keys, and send through an ID for pausing. They will then give us a resumeToken, which we store and send back when it’s time to resume.

Now this is all very good for production, but what do we do in our other environments? How are we gonna test this? This leads me to my next big tip.

Understanding the problem

Solution design is not just about writing code. It involves understanding the problem at hand, gathering requirements, and creating a plan that satisfies those requirements.

So for doing exactly that in our local environments, the best solution that most of you probably thought of as well is: Stubbing.

Now, my experience with stubbing was doing it very intricately in Java, where we’d create and process XML files with the response the API would produce when we’d give it specific parameters. I wasn’t looking forward to that.

But luckily for us, we use quite a few AWS services. And while investigating what would be the easiest and best combo of services to create my stubbing service, I’ve landed on Lambda with API Gateway. And boy, was it so much easier than the days of XML processing in SpringBoot Java.

So I wrote two Lambda functions, one for pausing and one for resume, and it would return different results based on the email that we sent through as a federation ID. Created the AWS API Gateway module and slapped those bad boy endpoints into our environments that were not production.

And to go even further beyond, since we use CDK, we’ve added constructs to properly track any changes to the service, rather than doing it all in the AWS console.

Now I got a bit too excited about relating this whole stub server process that I probably should’ve mentioned one extra step in between finding the solution and implementing it. And that is…

The solution design document

It is crucial to have a clear and concise design document. This document will be passed around to everyone, from devs to stakeholders. It should outline the problem statement, requirements, architecture, and design decisions. It should ideally also include any assumptions made and constraints faced and should be the reference point for the entire team throughout the project.

This can be anything from a Confluence file, GitHub readme or Teams Doc. It all depends on where your team keeps their documentation, which in my case was Confluence.

Now on the question of what this document should contain, here are a few sections that I’d recommend adding:

  • Requirements — Break down the problem that needs to be solved, what are steps necessary and what is the expected outcome.
  • Logical flow — In this section I usually put in swimlanes diagrams or any UML diagrams, depending on how complex the solution is. If the solution is chunky, try breaking it down into smaller bits.
  • Proposed solution (Architecture) — Write up the proposed solution, step by step. How will the application behave? How will the API behave? Write up the API endpoints that will be called and the expected response (if you’re feeling confident and ambitious, an API spec could go here). The flow of the proposed solution, basically.
  • Design details — I usually end up mashing this up with the proposed solution section since this section describes the architectural elements represented in the previous section but specific to the implementation. This is mainly for the benefit of the engineers implementing the solution. Some details that should be covered in this section can include service names, any resources or implementation logic where needed. Pretty much anything that adds value to the team while developing the feature or the product.
  • Anything else — Some other details you could mention are probably if you need to do some special error handling on the front end, or any other questions or considerations that need addressing. Maybe mention security requirements? Maybe some threat modelling? Or maybe if you’ve encountered any problems or have any other assumptions you could add them all in a section as well.

Obviously, you shouldn’t restrict yourself to only these sections! You can add anything that you feel would be relevant, but I would highly recommend at least having these sections.

It is super helpful that as you work on this document, to consult with your team and the people involved in the work, as they provide immediate feedback and suggestions if something feels off or missing. Solution design is rarely a linear process, and it often involves iterations and refinements based on feedback and evolving requirements. Emphasising the need for flexibility and adaptability in the design approach can help teams navigate changes and improvements effectively.

Our team has a Dev catch-up every other week where we discuss such problems, and in my case, it really helped to talk through the solution with everyone, as they’ve pointed out some things that I would’ve not thought about! As I said, I was a rookie in solution design when I started this piece of work.

This next tip might not apply to everyone, but I found it helpful for my team. And that is that after you finish your design document, all of your talks, and prep work, you should look into creating a:

Proof of concept

The best way of actually showing the solution in action is by creating a small Proof Of Concept (POC). Doesn’t need to be perfect as long as it roughly does what it’s supposed to. I found that after creating a POC and then moving into actually implementing the feature, anyone in the team could pick up the work. Since you had the design document with the overall flow and the POC with a rough idea of how it should go, it goes a long way toward creating a smooth dev experience.

In conclusion

This article is just scratching the tip of the iceberg of solution designing, however, it should be more than enough to get you started!

But, if you would like to read a more in-depth approach and overall a masterclass in best practices I highly recommend this article written by my colleague Sheen Brisals.

Let’s do a quick recap of our solution design top tips™:

  • Communication
  • Understanding the problem
  • Solution design document
  • Proof of concept

Solution design shouldn’t feel like a daunting task that you should be spooked to pick up. It’s a great opportunity to expand your knowledge arsenal of the software development process. It also does wonders for the way you communicate and approach all other problems. It teaches you what questions to ask, what areas to look into and who to talk to. And the best part is that everyone is there to help out if you ever feel out of your depth.

--

--