Principles of Good System Design

Based on this article

(Note that these are not presented as universal principles of system design, but rather ones that worked for this specific project. Hopefully they are useful examples, but I urge you to take a shot at your own list.)

1. Keep it as simple as possible to address today’s known problems

Don’t add complexity to the system to solve hypothetical problems we might face in the future. Thinking ahead is great, but we shouldn’t take on the burden of planning for eventualities that might not even happen. Let’s not try to boil the ocean.

If we can make the system more open-ended without adding a ton of complexity to the system or adding lots of work, that’s great. But otherwise let’s stay focused.

Can we make this simpler? Are we making too many assumptions about how this may need to be extended in future?

2. Ensure that it’s legible

A successful system should be easy for users to understand when they interact with the product. They will need to look at the UI (when we design it) and be able to roughly figure out what the parts of the system are.

For example, Slack clearly exposes itself, where it’s possible to discern the underlying system by looking at it – there are channels, inside each channel there’s a stream of messages, each message can have a thread, etc.

Can the correct user mental model be expressed via the UI? Is the architecture of the system evident in the interface? Will users be able to figure this out without an explanation?

3. Move complexity to infrequently used parts of the system

We will accept less efficient workflows and higher learning curves for one-time tasks if it means we get to make common tasks faster and simpler.

Assuming there’s a certain burden of functional complexity that the system must carry (Tesler’s Law), then think about where you can live with having more complexity. For example, it’s more acceptable for it to be difficult for a manager to set up a team (which will happen once) than it is for a customer support rep to reassign a conversation (which will happen dozens of times a day).

Does this system require too much complexity up front? Are the least-used parts of the system over-exposed? Which users interact with each part of the system?

4. Don’t take on non-core problems

Don’t get distracted by the implementation details. Remember, you’re not designing the entire product when you’re designing the system: you’re designing the major interrelated parts of it. The system design needs to describe the shape of the solution. It doesn’t need to answer every detailed design question.

Try to figure out what are the core things that the system can handle and what things you will be able to solve by designing the UI, or with clear workflows, or settings if needed.

Is this the right zoom level for this diagram? Do we really need to solve this part of the problem at the system level?

5. Build it to scale from simple use case to complicated use case

One of the dangers of moving upmarket (i.e. focusing on larger customers) is that you can alienate and create unnecessary complexity for your smaller customers. It’s too easy to design just for the needs of your most demanding users. The most elegant systems allow for simple use cases that then scale up as needed.

Intercom, for instance, is used by two-person startups who want a way to chat with their customers, and it is also used by huge teams with complex needs. You want a system that works simply for the little guy and scales up in complexity for the big guy.

What parts of the system are relevant to all users? What parts are niche?

6. Prioritize adjacency to the existing system

All other things being equal, choose a system design that’s most similar to what we currently have: less for us to build, less change for our users to adapt to.

System design is an ongoing process, rather than a once-off project. Your product will evolve, and anytime there is an expansion of what the product does, or a change in how the product operates, that’s where the adjacencies in the existing system becomes a factor to assess.

Adjacency is beneficial because it reduces change aversion or it reduces the barriers to understanding what the new version of your product is.

How hard is it to get to this from what we have today?