I lack experience in designing medium to large application. I tried to read system design content but not able to gain confidence.
How can I do the hands-on practice of system design concepts. Please your tips, resources, plan etc.
1. That has a functioning app
AND
2. Business is growing rapidly bringing more customers than the system can handle.
In other words you learn on the job by getting your hands burnt. I got lucky to have joined such a startup. Learnt a lot, from fixing DB queries, designing asynchronous order processor, using CDN etc. I worked on scaling up the full stack including stuff like connection pools.
So your best bet is to join such a startup. You will learn a lot by handling real user traffic. And also scaling isn’t homogeneous. For example, you make different trade offs scaling a search application Vs scaling a payment processor. So business use case and business domain does matter.
It absolutely bothers me that the resources out there are few and far between. It is hard to change that. I encountered occasionally resistance in organizations to share more openly the process, e.g. I suggested video taping it and uploading the video as a start. Naturally, plenty of confidential information can be disclosed in such design sessions, so enthusiasm about sharing recordings is rather low, even when everyone in the room agreed to be taped in the first place (which in itself is almost impossible).
I am bothered by engineering topics that have this „tribalism“ way of education. In networking one of these areas is BGP. No one lets you near Border Routing until you can do it perfectly, because of it potentially catastrophic impact (Pepperidge Farms remembers Pakistan Telecom hijacking YouTube!). When I tried to solve that one I ended up spinning up a whole ISP which’s sole purpose is to play with and break BGP. [1]
For system design I haven’t found a solution yet, ideas welcome. In the meantime, all you can do is read the little that is available (e.g. [2]) and try to talk to as many practitioners as possible, asking them to share or simulate a session privately.
1: https://www.nonattached.net 2: https://cloud.google.com/blog/products/management-tools/sre-...
- System Design Interview – An insider's guide: https://smile.amazon.com/gp/product/B08CMF2CQF
- System Design Interview Vol 2: https://smile.amazon.com/System-Design-Interview-Insiders-Gu...
- Designing Data-Intensive Applications: https://smile.amazon.com/gp/product/1449373321
- System Design Primer: https://github.com/donnemartin/system-design-primer
Especially: https://github.com/donnemartin/system-design-primer#how-to-a...
- The Architecture of Open Source Applications: http://aosabook.org/
One: How do you get better at systems design? Build stuff -- lots of stuff. If you're interested in designing particular kinds of systems (say, planet-scale web services...), then get a job at a company that does that kind of thing.
Two: How do you get better at systems design interviews? That's much easier; you can just throw money at the problem. Use one of those paid mock-interviewing platforms where you can hire FAANG interviewers to anonymously interview you and give you feedback.
I just went through this interview prep and got the offers I wanted, so I can offer you a data point. It took me < 20 mock interviews (total cost of < $10K) to go from "I have no idea what I'm doing" to "I'm not worried about this part of the on-site interview loop." Admittedly, I have a decent bit of experience architecting systems at scale, so I was mostly using this approach to refresh my memory (heading back to a Big Tech job after several years of retirement) and get familiar with the interview format.
There are some common resources recommended for this sort of thing if you want to also make sure you've read the right content. The most helpful resources for me were the DDIA book [1] and the "Systems Design Interview" YouTube channel [2]. Both are great for breadth and getting exposure to a ton of different concepts -- after that, you can follow your nose (or the book's bibliography) to get depth on whatever you're most interested in.
Good luck with it! It's a deep and really fun rabbit hole. I suggest you find a particular type of system that you're really interested in; start pulling on that thread, and you'll inevitably find your way to all kinds of other fascinating systems-design topics as you go.
Second, I think the best way to learn is to just work on a lot of systems. Sometimes your ideas will work out. Other times, you will wish you had become anything other than a software developer. Both states are equally helpful. It’s nice to write good software and have things work out. But you’ll learn a lot more from the projects you can only fix with ‘rm -rf’.
Third, try to get as wide a range of experience as possible. Be the lead designer on one project. And be extremely junior on another project. You’ll learn as much from implementing another person’s designs as you will learn from implementing you own.
And finally, have fun and be cool to everyone you work with. You will meet a lot of beautiful people and a lot of assholes. But if you love writing software, you’re part of the tribe. Make it positive and be cool to others. In twenty years, you won’t remember half of what you know now. But you will always remember developers who were kind to you when you were learning. Be one of those memorable developers…:)
Good luck. It’s a hard path but I know you can do it. You’ve proven it by starting off here.
It's essentially an apprenticeship: you work in teams and as you gain experience, you contribute progressively more and bigger ideas. One day, you get a job where the design is your responsibility.
1. Almost all distributed systems has a global load balancer sitting in front, which will distribute your traffic to nearest possible server.
2. Decide how do you want to make your DB replication to happen. Is it active/active, active/passive, P2P, etc ?
3. What do you choose between Consistency and Availability when Network Partition happen? Some databases like Cassandra are eventual consistent.
4. Any asynchronous tasks will need to use queuing service.
5. Any performant API will need to use Caching and CDN.
- what happens if this stuff fails (and how to test it, how to analyze it)
- what attack surface that stuff has
- how to scale if it receives x10 requests or becomes x10 bigger
- how can you explain to a new coworker how it works, how all the decisions were made
It will rapidly give you the real understanding and practice. System design is about dealing with problems, making compromises. It is very hard to make an effective book (probably even impossible - it should probably be an interactive course at least) that will walk you through this process, not just throw a bunch of "patterns" at you (which is not useful and can infect you with the shallow cargo-culting that our whole industry is so full of).
I'm going to be exploring how to go about it, how to massively over-engineer things for the sake of learning, as well as build minimalistic aspects of the games.
There will be `Main Quests` where we build a simple game, and `Side Quests` where we go off the wall and explore new tech.
I just started tonight! So it's definitely a WIP
The great thing about smaller projects is that you can take risks with them.
Build something small that uses a message queue. Then do a project that integrates with some web APIs. Then try building something that implements GraphQL. Then try integrating full text search.
When you get the chance to work on something bigger I guarantee you'll find this experience incredibly valuable. Larger systems tend to look a lot like smaller systems, but messier and more complicated because more people have been involved in helping grow them as their requirements have changed over time.
1. Not clarifying the problem. The very first thing out of your mouth should be a series of questions that helps you define the requirements more clearly. Identify use cases. Try to understand the scale; questions that start with "how many" are good ones.
2. Not being concrete. For example, I had a design problem I'd give people that usually wound up with them sending lots and lots of messages in real-time from one system to another. But when pressed, very few people were able to describe the contents of those messages in any detail.
Just thought I'd pass that along in case it's helpful to you. And I'll second what a lot of other folks here are saying: the best way to learn this is to get experience.
As you said ,you have a lot of small apps, mabey you could do something to link them together, and build a middle layer service for all the apps. In this progress, you should consider all the part of designing a distrubuted system, it could help you a lot, I guess.
Perhaps it's not the best way to improve the ablity for system design, it works a lot on me at least.
* i18n/l10n: Display labels in different language and correctly format the counter value for your user (1'000 vs 1.000). A user should be able to switch country
* Allow users to register and create their own counters
* Store the counter value in database hosted somewhere
* Store content stuff (title, labels, etc.) in a headless CMS and integrate with it.
* Set up build pipelines for your project
* ...and more :)
If you want hands on experience, pick an open source app in the language you know and deploy it somewhere and load test till it breaks and see which part breaks first. It could be your load balancer can’t handle that many connections or you app server rubs out of memory or the db comes to a crawl. The more real world you can make load test queries the better.
At the very least you’ll get hands on experience.
[0] https://nealford.com/katas/#:~:text=Architectural%20Katas%20....
Take a fast moving input data stream, and map it to some slower moving output streams.
Use a message queue, a web tier, a worker, and implement private and public caching internally in something like Redis. Implement HTTP caching.
Implement backups, failover, and recovery. Create runbooks and checklists.
Secure everything with MFA auth for admin-type users and design and implement lesser privileged user access.
Design and implement RBAC.
Add reporting, logging, fault-tolerance.
Make it platform agnostic and support multi-tenancy, i18n, and WCAG.
Support and test for HIPAA and GDPR compliance.
Document the whole thing.
Figure out how to write automated tests for all of these aspects.
I suspect that people would take issue with the exact implementations I use, but they tend to work fairly well, and have lasting power (I wrote an API for imaging devices in C that was still in use, 25 years later).
I wrote a backend system that is currently in use, worldwide, by thousands of people (I wrote it about twelve years ago), but has been taken over by a new team (I hardly have anything to do with it, anymore). I also wrote a few clients; most of which have been retired. The system I'm working on now, leverages it, and mixes it with another one I wrote (just a couple of years ago).
My way won't win Buzzword Bingo, but it WFM. YMMV.
I'm happy to share, but I've found that not everyone wants to do things the way I do, so I'll do so out of the public eye. I have a few generic things, here[0], that I've written, over the years, talking about some of my techniques.
I think I’m inclined to incrementally solve potential problems with the system (as introduced by the interviewer), where a lot of these interviews seem to want you to anticipate all issues.
So asking lots of questions about what they want is probably a first.
Ask yourself:
- What constitute a _good_ infrastructure?
- Something flexible/adaptable ?
- Something predictable ?
- Something resilient ?
- Something easy to monitor ?
- Something else ?
- How do you prioritize these, who gets to decide which one matters most...
Architecture is asking a lot of questions, inviting others who will benefit/use your work into the decision making process.
One thing that I learned that is still helpful to me today is try to push as many decisions as possible to later, keep the door open for futur choices. Every system architecture is part invention, part discovery. As you put together your foundation, new requirements/restrictions will appear and you'll be happy to have the freedom to make some of your decisions then.
and
https://www.amazon.co.uk/Designing-Data-Intensive-Applicatio...
are great
^ this guy is amazing. His systems are implemented all the time.
The best way to get hands-on practice is to do just that. The tech part of system design is nothing; it's dealing with an organization and its myriad biases, politics, and reservations that'll teach you the most about the practice.
Questions for stage 3: Do all customers/clients really need to be able to access all other customers/clients state/data in parallel and real time ? What can be cached ?
Couple points from me:
Have someone conduct your mock interview, once you think you are ready. Also, don't hesitate from appearing in an interview at a company which you don't plan to join. Another good way to practice and demonstrate your skills.
Are you a small business owner that preparing for going viral one day? Keep improving your system bit by bit. Maybe add a caching layer today, load balancer tomorrow, a job queue somewhere down the road and scale up your database now and then. And probably YAGNI imo.
If for job hunting, other comments had better suggestion
- learn docker / docker-compose - tie a websocket server, a task queue, and 2-3 http microservices together - you don't have to have many resources, maybe 4-5 endpoints that go through all services - have a client javascript front like react - (bonus for grpc communication for intermediary connections between microservices) - try to break it/ fix it as much as you can. - along the way you'll introduce yourself to timeouts, retries, rate limiting, and other secure practices.
watch guarav sen or hussein nasser on youtube - they are extraordinary resources for aspiring and even competent backend architects
For reference we do paid 45 mins mock interviews. In case you are interested, dm me and I can share more details.
That being said, there are a few well known examples of systems that are somewhat complex right from the start. Ecommerce comes to mind: build a configurable ecommerce framework that supports multiple stores, multiple vendors, multiple channels, CC and cash payments, multiple currencies, international delivery etc.
do this with bigger & bigger end vision but with a doable MVPin mind.
look at good examples.
open source the result,
https://www.makepostsell.com/ (python, Pyramid, sqlalchemy)