AWS Builder Center
System Design for Beginners: tips from an ex Amazon Software Engineer

System Design for Beginners: tips from an ex Amazon Software Engineer

System Design felt overwhelming when I started at Amazon. There were too many terms, too much to learn, no clear starting point. After years of building large-scale systems, I now know better what actually matters to design a well rounded system: how to define requirements, build technical foundations, master trade-offs, and prepare for system design interviews. In this article, I will walk you through what I struggled with so you don't have to, and give you a path to improve your System Design skills.

Developer Advocate @ AWS

How I started in System Design

I joined Amazon as an SDE Intern in 2020. SDE stands for Software Development Engineer and they are the people who take care of the entire software development flow, from design to development, deployment and maintenance.
As an intern at Amazon you are not expected to have System Design skills yet, but I knew that if I wanted to progress in the role I would have to figure it out. But nobody really sits you down and says "Let me break down System Design for you", people just seem to do it. So asking where to start feels like a stupid question.
It's not. And in a universe so complex and large of technology it's easy to get overwhelmed. So here is what I learned in my engineering years to help you ease into it.

What even is System Design

As you start exploring the System Design world you may come across many different terms: design, architecture, models, patterns, styles, infrastructure...
I used to get stuck between all of these words, thinking that if I didn't even know what they meant, how was I supposed to know what to invest on? I asked a mentor once what was the difference between architecture models, patterns and styles, thinking that answer would finally make it all come together for me. They answered me: "If this is what it takes to design a good system, then I'm just as clueless as you are".
I'm sure there is a textbook definition for each of these terms, and a proper way to use them. But my mentor's response showed me that it's not about memorizing a thousand definitions. It's about critical thinking and action.
So detaching from the never ending vocabulary, System Design is, simply put, the act of transforming a problem statement into a technical solution that solves it. That's it.
Now onto the next scary step, let's talk about how to do it.

The Amazon approach to system design

Amazon has a very strong culture that is supported by very strong processes. Of course it is not the only valid way to think of software, but two strategies taught me valuable lessons.

Working backwards

Amazon's mission is to be Earth's most customer centric company. We apply this by always starting with the customer problem and what their end experience should look like, and then work backwards from there.
It all starts with a document called PR/FAQ, short for Press release/Frequently asked questions. This document creates a vision of where we want to go before we define how we are getting there, and puts everyone involved on the same page.

Doc writing culture

But doc writing does not stop after the PR/FAQ. Amazon is known to almost always favor written documents instead of PowerPoint or other visual and spoken presentations.
This is because a written document forces you and your readers to focus on facts and data. It's easy to get taken by a good speaker with a stimulating presentation full of animations, transitions and quirks. Our brains get caught up in the novelty and our critical thinking decreases. But a simple document with cold hard arguments, based on cold hard data, will invite our minds to actually ponder over them.
For this reason everything that comes after the PR/FAQ at Amazon is still a document. This includes requirements from different stakeholders, high and low level designs, testing and deployment strategies, etc. Everybody sits together, reviews in silence and writes down their thoughts. We then discuss point by point, until we have a satisfying solution.

How to succeed at system design

You may be wondering what the Amazon culture has to do with System Design. It taught me to focus on the actual problem and base my decisions on data oriented arguments. Going a bit further on this, here are some tips and tricks to succeed.

1) Understand your business context deeply

As developers, it's easy to get hypnotized by technology. We may get excited about a new feature or programming language and be curious to try it as soon as possible. But a good developer is before anything else, a good problem solver.
We need to have a deep understanding of the domain we are working on, its business context and the problem at hand. Ask yourself: what does my system or product currently do? Why does it work this way? What needs to change and why? Who are the users and what do they expect?
This is the art of defining requirements and we can divide into two types:
  • Functional requirements: what the system should do. These describe the features and behaviors users interact with. For example, "users can upload a photo" or "the system sends a confirmation email after checkout".
  • Non-functional requirements: how the system should behave. These are the quality attributes that don't map to a specific feature but shape the entire design. Things like performance (response time under 200ms), availability (99.9% uptime), security, scalability, and cost constraints.
A good system design starts with a clear list of requirements and a good understanding of the current scenario and where we want to go. Remember, technology is just the means, we are here to solve real problems.

2) Have strong technical foundations

Telling you to focus on understanding the problem, does not mean you won't need tools to create a solution.
This is where your technical knowledge will come handy. But there is so much you can learn about, that it's hard to know where to even begin. Let me give you some macro areas to think about when you are designing any type of system:
  • Frontend vs backend: we call frontend the components that create an interface for users to interact with, your webpages and apps. Backend on the other hand is the logic behind it. You may want to prioritize diving deep into one or the other depending on your preferences, but I recommend having a general understanding of both
  • Compute: this is the infrastructure that will be responsible for running your code. You will see people talk about servers, serverless and containers. A good way to start learning about it is by understanding what a server does and how to manage it. I have a dedicated article on this subject  that will give you a walkthrough on servers and introduce the serverless world
  • Databases: the most basic decision you can make in terms of databases is having a SQL or a NoSQL database. Start by understanding the difference between them and in what scenarios it's best to use one or the other. From there you can go into subjects like database performance and caching
  • Authentication/authorization - authentication means a system knows who you are while authorization means it knows what you are allowed to do. Unless you are a security specialist (or want to be one), you don't have to understand how this works in major detail, but start by getting to know strategies and services that help you handle this.
  • Networking and communication: systems are made of components that need to talk to each other. Start by understanding how APIs work, the difference between synchronous and asynchronous communication, and what protocols like HTTP and WebSocket do. Knowing when to use a queue versus a direct call will save you from a lot of headaches down the road.
  • Architecture patterns: this is the subject that used to keep me up at night, until I found out it's not rocket science. Architecture patterns are simply frameworks that solve different types of problems with different architecture structures. Studying different patterns will help you create a repertoire of strategies that you can reuse. I recommend starting with client/server and event driven architecture (here  is an article that may help) which are two of the main patterns we see in real systems.
I used to tell my mentor (yes, the same one of the architecture question) that I had many "technical shames". These were subjects that I had heard of but didn't quite understand how they worked or where to apply them. This brought me shame and that shame paralyzed me. Years later I learned that that feeling was ok, it's an insecurity that everybody experiences and you can use it to choose which subjects you should invest most on.
Remember that you also don't have to know everything to get started. It's ok to start with a simple working solution and then get more complex as needed.

3) Master the art of trade-offs

Ok, but answer me this: is it best to run your application on managed servers or with a serverless solution?
If you've been a developer for a little while now, or have seen how more senior engineers work, you may know that the answer is: it depends. The answer is always "it depends", because no solution is the best fit for every single scenario. This is why trade-offs are the most important aspect of a design. They are the pros and cons of each alternative that you consider when deciding on a solution.
As you get into System Design, you will quickly notice that there is no "perfect" or "right" solution. Every decision you make comes with consequences, that may be good or bad for your use case. True system design ability comes from being able to identify these consequences and weigh them against the requirements to make informed decisions.
In our question about managed servers versus serverless, for example, you may prefer running your code on a managed server if your workload is predictable and somewhat constant. On the other hand, you may opt for serverless if your system receives sporadic workload and you don't have the bandwidth to maintain servers.
Don't look for perfect, look for most adequate for the current problem.

4) Don't do it alone

Impostor syndrome was my biggest companion throughout all of my career. We've grown apart over the years, but she still makes sure to visit me periodically.
This isn't an article on impostor syndrome, but I can't ignore how much suffering it brought me in my career and System Design journey. I used to think that my knowledge gaps were a sign I was a failure, not that I was simply learning. Because of this, I thought I had to do it alone, in secret, and only come out to the world when I knew it all.
Looking back, I know my journey would have been a lot smoother if I had allowed myself to ask for help and share my doubts and experiences. That's why I would tell you, if you can, share your process with others. Study with friends, ask for help from more experienced colleagues, join communities (I personally recommend the AWS Student Builder Groups  and User Groups  😉).
Don't feel like you have to hide yourself for not knowing something. Every expert, in any subject, was a beginner at one point, and people will have a lot of support to offer you if you let them.

Designing for a classic interview problem

An extra tip I want to leave here is the classic practice makes perfect. In System Design, this means designing a few systems that require a different set of strategies, even if just in theory. As you learn how to solve different design problems you start cultivating technical tools that you can reuse in future designs.
Each scenario will have its own specificities, but there is a set of steps that you can follow that will help you tackle any of them, and hopefully make System Design interviews less scary:
  1. Understanding the problem: as I said before, we have to have a clear understanding of the problem before anything else, so start by drawing a very high level diagram
  2. Identifying requirements: this is where we get more specific on the functional and non functional requirements
  3. Predicting traffic patterns: how many users do you expect your system to have? What functionalities do they use most? Is there a specific time of the day? These questions will help you define how your infrastructure needs to support the reality of usage
  4. Designing high level components: now sketch out the main building blocks and how they connect to each other, but without specifying technologies
  5. Defining APIs: decide what endpoints or contracts each component exposes, what goes in and what comes out
  6. Selecting a tech stack: pick the actual technologies (framework, database engine, cloud services, etc) that best fit your requirements and constraints
  7. Considering implementation constraints: go through your requirements once again and check if there is anything that should be dealt with during the implementation phase and flag it
If you want to explore these steps further, I created a video for the AWS Developers youtube channel  walking through this framework I use to solve any system design scenario and applying it to a classic System Design interview problem. Check it out and let me know what you think!

Closing thoughts

Today I am no longer an SDE. Although I still consider myself a developer, I am no longer building and maintaining large scale systems. But my studies of system design gave me skills that still help me to this day, both in my current role as a Developer Advocate, and in my personal life.
Of course I had gains in my technical knowledge, but we can go further and more philosophical than that. In System Design, every choice comes with a price. You gain something while also losing something, and mastering it is knowing what aspects are crucial and what you can let go of to make a decision. At the end of the day, isn't this what life is all about?
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article