Problem Breakdown: Contact Us page

· problem-solving

Here is an article where we try to decompose down a problem into pieces. The aim is to share my process of breaking down problems into smaller pieces. It is also an exercise for me. There is no coding here. There will be some details on interfacing between the different components.

Whenever we think of such things, we typically have something in mind around what a contact us page looks like. How it behaves and how much do we need to think about it is usually dependant on the specifications. Nowadays there is third party services that offer a solution for this kind of problem. We will build our own.

Before that, let’s establish why we want to break down the problem:

  • Reveals different parts and how they interact
  • Makes clear the required steps to finish the task
  • Reduces complexity when thinking around the problem
  • Can be translated into unit of code delivery

I hope that convinces you why. Often just trying to think about the problem will help us greatly understand the next steps from an engineering perspective.

The problem’s specifications are:

  • A contact us page with a form to write an enquiry/support/contact request
  • Have verification mechanism against automated bots
  • Store all requests
  • Notify admins of a new request by email

Actual specifications will be more specific with clear expectations of the outcome. Our specifications need not be too specific as the overall solution will generally be a result of the overarching specs.

Right off the bat, there are backend and frontend components. We will need to store the data in our own database. There was no mention of an admin console to access requests and lets not think of that right now.

From a design viewpoint, the page can be built independently from the backend then we can hook them all up at the end. This is where can diagram the spec and the interactions if you like visual explanations.

The first thing I would do here is to create the contract between the backend and frontend. This task is important because this is the point of divergence, i.e. after agreeing on this, the backend and frontend work can start in parallel.

An example contract would be defining the endpoints involved and the signature. To create a contact request, we just need one for this page. I will go with a RESTful API approach but you don’t have to. Something like:

/api/v1/contact/request

this is a POST request. It expects the following JSON payload:

  • First Name
  • Last Name
  • Email
  • Subject
  • Content
  • ReCaptcha token

Note the ReCaptcha we will use because one of our requirements is to ensure all requests are not from automated bots. Google’s ReCaptcha is very good and has been used for the longest time. So the expectation with stakeholders we settled on is to prompt the user on the frontend with a ReCaptcha challenge like choosing which image is contains a car and those sorts of things. If a user passes a challenge then will choose to call the endpoint from the frontend otherwise will show an error or retry.

The possible responses we will return are:

  • 200 status code - the request is successful
  • 401 status code - error in the validation, not all fields were adhering to the contract payload
  • 403 status code - the ReCaptcha token was verified but failed from Google’s end

Will not consider cases where Google is down. That is a rare thing and we should always return 500 status code when such things happen as they’re outside our control. Though it also depends on the way we design our backend which will discuss soon.

Sweet. We’ve agreed on the contract. Let’s break down the frontend. We shall have the following steps:

  • Build out the page skeleton
  • Add all non-form page elements
  • Add the form
  • Implement the logic that calls the backend when submitting the form
  • Add client side validation including ReCaptcha
  • Implement error handling
  • Implement the after submit flow. This could be a redirection or popping up a toast notification.
  • Add links to the page from other places in the site
  • Add proper SEO metadata to the page
  • Write unit tests for the various components

That’s pretty much what the front end breakdown would look like.

You can usually mock the backend with a mocking service to simulate an already built endpoint.

The backend is more involved in a different sense. We know the endpoint definition but now we need to worry about the data storage. It really depends on the scale of our website. Contact, support and enquiry requests don’t usually occur at a high frequency like more critical path traffic. Therefore even if the website has 10 million daily active users, I wouldn’t expect more than 1 request per second equating 3600 requests an hour and that is usually pretty high.

I will not consider any scaling issues as that is outside the scope of this article. The most important thing in the backend is to agree on the proper database entity schema.

The proper database entity schema design depends on how the data is expected to be accessed and what we want to store. Since we’re storing text then we can get away with any relational database. The expected text by user wouldn’t probably exceed 5000 characters.

Now we got that out of the way. The endpoint would execute in the following order:

  • Validate the payload and if not valid then return 401 status code
  • Verify the ReCaptcha and return 403 status code if not passing verification
  • Insert to the database
  • Send an email notification to the stakeholder about the request and store it
  • Return a 200 status code

Those steps above can each map to a separate task.

It is possible that inserting to the database and/or notifying stakeholders may fail. We should probably add some retries and fail as 500 status code if exceeded retry count.

Great. If the scale to the backend was way greater then we could probably store that payload as an event in an event stream. Consumers would pick up that event and process things. That is a design I would go with if the system has an extremely high throughput and have a lot of processing to do post submitting a contact request, i.e. if there is 3+ consumers of an event. I always advise to keep this as simple as possible.

Great stuff. We’ve broken down the spec down into multiple pieces. In terms of resourcing, a lot of parts can be worked on by multiple engineers at the same time. It really depends on what the delivery expectations are.

Similar design planning is usually a good training for a junior engineer to get to know what to think about and do before jumping into the code.

Even though this seems like a simple thing, we’ve been able to show that there is a lot of moving parts here. Scale definitely has a role in influencing how we design the problem. The remaining thing is to hook the frontend to the backend if not already done.