Back Arrow
From the blog

5 Key Software Architecture Principles for Starting Your Next Project

In this article, we will touch on where to start designing the architecture and how to make sure that you don’t have to redo it during the process.

Andrey Stepanov

CTO at ByteMinds

How deeply should you determine the architecture of a project at the start? What criteria should you use? What should you focus on from the beginning?

In this article, we will touch on where to start designing the architecture and how to make sure that you don’t have to redo it during the process.

But first, let's answer the question - why?

For a business customer, it might seem that deeply considering the architecture in the early stages isn’t very important. You can often hear something like, "Let's quickly build something functional, and then we can make it pretty with diagrams."

But this is actually a misconception. Of course, even without a formal architecture, developers will come up with something. For example, they might take a ready-made architecture from a textbook or rely on the one they have experience with. And, in the end, something will get "built". But, based on our experience, most often you’ll get something like this:

It seems like you’ve built a structure. And it has all the features - windows, doors, balconies, a roof. And yes , you can live in it. But how long will it stand? It’s hard to say.  It’s difficult to assess its quality and whether it meets the needs of those who will live in it. Additionally, due to architectural inaccuracies, the construction may be stopped at any moment because continuing would be too dangerous or costly. You might need to demolish it and start over. 

That’s why planning software architecture from the start is critical. Today, we will discuss a set of rules that may not seem advanced but will help you lay a solid foundation for your projects. Inspired by Ray Dalio’s book “Principles”, I’ve developed basic principles for software architecture that I actively use in my work when starting a new project.

Principle 1: Architecture is subordinate to product and business goals

Not the other way around.

What happens if this principle is violated? When we start prioritizing the internal architecture over the needs of the people who will use the product, we forget why we’re creating it. We become "architectural astronauts", creating overly complex solutions for non-existent problems, wasting the team's time and the business’ money.

It’s less of a problem in large companies where they can afford costly experiments. But for small companies, this kind of resource misallocation can be disastrous. For example, instead of  building a simple blog, a developer might get carried away and implement microservices, Kubernetes, and all the patterns they know - building a "mini-spaceship" that never takes off. 

According to management textbooks, an ideal workflow starts with a company strategy, followed by a direction strategy, and then a product strategy. And the architecture should be derived from the product strategy, and based on the architecture, the code is written. I agree with this because lower-level decisions should stem from higher-level strategies. But in reality, many projects start with only a vague vision and no  clear product strategy. It may exist in theory, but no one has documented it.

Software architecture is primarily about understanding the goals - who needs it and why. The architect must understand the product’s economics: how much revenue it should generate, how much the owners are willing to invest, and the time frame for launching it. Understanding the project's future is equally important.

There are tools available that help you see and understand how your product fits into the business and operates on different levels. We use some of these tools during the analytical stages. All of them provide a vision of the product and help clarify why we are writing code:

Principle 2: Architecture defines systems, their boundaries, and connections

Seems obvious, right? But let's dig a bit deeper.

Imagine looking at a plant section under a microscope. You’d see large and small cells.

The largest concentration of tissue is often at the boundaries between the cells. The same applies to systems in software architecture—what happens at the boundaries and connections is often the most critical part. What’s inside is shaped by these external connections.

A high-quality definition of subsystem boundaries and understanding types is the basis of architecture.

If this principle is ignored and boundaries and connections are not properly defined, disappointment follows. A client comes with an approximate vision, and the team jumps into iterative work without carefully defining the key system boundaries. For example, you might find out halfway through development that a crucial product element requires integration with third-party systems in an unsupported way, leading to costly redesigns.

Example: while developing a personal account for an online store, it turns out that the ability to communicate with personal managers is critical to the business, but the CRM doesn’t support real-time messaging. Imagine discovering this after spending 50% of the budget.

That’s why boundaries are essential. To address this, we often use a variation of the diagrammatic system context from the C4 model during the early stages of work. Here’s an example:

Let's say we have a system - let’s call it a "delivery service". There are people (clients, administrators) who use it and other systems with which it interacts (delivery services). We must register and consider all these connections, capturing the context of the entire enterprise. 

Principle 3: Architecture works with two constraints: hardware and people

Architecture is always about constraints. Two fundamental constraints prevent us from waving a magic wand and suddenly getting a working result.

In our case, the constraints are hardware and people. Architecture must provide solutions for both.

Hardware constraints are about understanding the available equipment. We’ve all encountered applications that don’t run smoothly on powerful devices due to inadequate optimization (hello, Notion!). 

As architects, we need to consider where our software will run, what devices and operating systems it will use, how much data storage is required, and network performance. And since we live in the physical world, everything breaks eventually. 

When starting a new project, we try to work with the most basic numbers.

Examples of fundamental constraints:

https://gist.github.com/hellerbarde/2843375 

See also: https://vercel.com/blog/latency-numbers-every-web-developer-should-know 

Understanding product requirements and matching them to these constraints often begins with a simple estimate of key parameters based on the product strategy.

For example, for one sports project, we estimated the number of coaches, teams, and players, and how often they would use the platform. From this, we determined the necessary hosting setup and its cost. It’s also important to consider data volume (e.g., video, images), which can lead to cost and storage limitations or hit pricing tiers with hosting providers.

Sidenote: I am not suggesting premature optimization - trying to squeeze out maximum resource efficiency early on. Instead, I’m advising that you understand the actual business requirements and ensure your system performs adequately for them.

The second constraint is people. They have limited attention spans, limited knowledge,  and different ideas about how things should work. As architects, we must always keep in mind who the architecture is for.

A developer can’t keep the entire project in mind at once. Most of their time is spent reading code, not writing it.  In this sense, the architecture serves as a map, helping them navigate through the product and understand what changes need to be made and how those changes impact the system.

Architecture should work for the people who will interact with it. Understanding their skills and needs is crucial. If they aren’t available now, you’ll need a plan to onboard them—whether through hiring, contractors, or another approach.

Consider who will be working with your architecture:

  • Development team: sometimes we know who will develop the project’s architecture, but other times, especially in large companies with tenders, it’s less clear.

  • Internal customers and controllers: these may include CTO or an architectural committee ensuring adherence to the company's broader IT strategy.
  • External regulatory bodies: in industries like finance or healthcare, these bodies will review products before launch.
  • Support and development teams: often, different teams handle product development and ongoing support.

Depending on their knowledge and skills, you’ll need to tailor your architectural approach - simplifying where necessary or investing more time in training for complex solutions.

When thinking about “architecture for people” it is important to consider:

  • Domain separation: Splitting a large system into domain areas (sales, order processing, product catalog, etc.) can improve team efficiency. This avoids overlap and conflict. In domain-driven design, this is known as "bounded context."
  • Key architectural approaches: Decide whether to use a modular monolith or microservices. If it’s the latter, describe the interaction patterns.

If you neglect either of these architectural aspects—hardware or people—you’ll likely end up with a slow, fragile, unreliable system, or an over-complicated product where people struggle to understand and work with the code.

There are many approaches and engineering practices in software architecture textbooks, but if we look closely, we will notice that each one aligns more closely with one of these aspects:

Your task is to select those approaches that best fit your team and product, and then clearly communicate them to your team.

Principle 4: Architecture must allow the project to grow and evolve

Software architecture doesn’t just support the current product; it should enable growth and change in the future. The question isn’t "How do we design it so we never have to redo it?" but rather, "How do we design it so we don’t have to redo it in the next few months?"

Think of software architecture like a landscape design. Code will grow and expand, and some parts will fade or become obsolete. Like gardeners, we must organize and maintain it. We can, for example, transplant a "tree" (a block of code) or rearrange "flowerbeds" (modules) in our project. Unlike construction architecture, we have more flexibility in software design.

The project architecture should mainly focus on future changes to the project.

 We must plan for growth—load increases, new features, additional users, new interfaces, or integrations. After reviewing the product roadmap, it’s useful to highlight the areas likely to change and focus on those.

As software architects, we must prepare the "beds" for future growth and always keep in mind what might grow within the product.

Principle 5: Code and architecture should be self-describing

In short: sometimes it is easier to write code than to draw a diagram.

Diagrams become outdated as the code evolves, and unless they’re updated regularly, they become useless.

Situations when code is better:

1. A code example of implementing a typical feature can better demonstrate to the team how different modules interact than a diagram. Walk the team through the code and use it for onboarding new developers.

2. Code examples of common patterns—such as microservice calls, logging, or authentication—can provide clarity. If there’s no time for a full feature, collecting typical patterns into one guide is helpful.

3. Auto-generation of code documentation: API documentation (requests, parameters, data formats) can be generated automatically. We often write server code with request and response objects, and generate an OpenAPI/Swagger specification (e.g., via Swashbuckle in .NET). There are rarer but effective examples like generating architecture diagrams based on code for infrastructure (e.g., K8S).

Additionally, tools can help developers navigate the system in absence of detailed architecture docs:

  • Tools like NDepend can show how modules are related. The advantage is that the diagram is not just a static picture but an interactive map that lets you zoom into individual modules.
  • Generated ER diagrams for databases can also be visual, especially with some manual grouping afterward.

For large projects, these tools will only help with parts of the application. But even with "spaghetti architecture," at least the map will be accurate.

Conclusion

If you follow these principles, your architecture won’t be arbitrary, overcomplicated, or underdeveloped. You’ll be able to create a solid architecture that’s appropriate for your project and its current stage assuming, of course, you have the time and skills!

Good luck with your architecture!

It's easy to start working with us. Just fill the brief or call us.

Find out more
White Arrow
From the blog
Related articles

Assessing Algorithm Complexity in C#: Memory and Time Examples

Anton Vorotyncev

Today, we will talk about assessing algorithm complexity and clearly demonstrate how this complexity affects the performance of the code.

.NET

Top 8 B2B Client Service Trends to Watch in 2024

Tatiana Golovacheva

The development market today feels like a race - each lap is quicker, and one wrong move can cost you. In this race, excellent client service can either add extra points or lead to a loss dot to high competition.

Customer Service
Client Service

8 Non-Obvious Vulnerabilities in E-Commerce Projects Built with NextJS

Dmitry Bastron

Ensuring security during development is crucial, especially as online and e-commerce services become more complex. To mitigate risks, we train developers in web security basics and regularly perform third-party penetration testing before launch.

Next.js
Development

How personalisation works in Sitecore XM Cloud

Anna Bastron

In my previous article, I shared a comprehensive troubleshooting guide for Sitecore XM Cloud tracking and personalisation. This article visualises what happens behind the scenes when you enable personalisation and tracking in your Sitecore XM Cloud applications.

Sitecore

Server and client components in Next.js: when, how and why?

Sergei Pestov

All the text and examples in this article refer to Next.js 13.4 and newer versions, in which React Server Components have gained stable status and became the recommended approach for developing applications using Next.js.

Next.js

How to properly measure code speed in .NET

Anton Vorotyncev

Imagine you have a solution to a problem or a task, and now you need to evaluate the optimality of this solution from a performance perspective.

.NET

Formalizing API Workflow in .NET Microservices

Artyom Chernenko

Let's talk about how to organize the interaction of microservices in a large, long-lived product, both synchronously and asynchronously.

.NET

Hidden Aspects of TypeScript and How to Resolve Them

Dmitry Berdnikov

We suggest using a special editor to immediately check each example while reading the article. This editor is convenient because you can switch the TypeScript version in it.

TypeScript

Troubleshooting tracking and personalisation in Sitecore XM Cloud

Anna Gevel

One of the first things I tested in Sitecore XM Cloud was embedded tracking and personalisation capabilities. It has been really interesting to see what is available out-of-the-box, how much flexibility XM Cloud offers to marketing teams and what is required from developers to set it up.

Sitecore

Mastering advanced tracking with Kentico Xperience

Dmitry Bastron

We will take you on a journey through a real-life scenario of implementing advanced tracking and analytics using Kentico Xperience 13 DXP.

Kentico
Devtools

Why is Kentico of such significance to us?

Anastasia Medvedeva

Kentico stands as one of our principal development tools, we believe it would be fitting to address why we opt to work with Kentico and why we allocate substantial time to cultivating our experts in this DXP.

Kentico

Where to start learning Sitecore - An interview with Sitecore MVP Anna Gevel

Anna Gevel

As a software development company, we at Byteminds truly believe that learning and sharing knowledge is one of the best ways of growing technical expertise.

Sitecore

Sitecore replatforming and upgrades

Anastasia Medvedeva

Our expertise spans full-scale builds and support to upgrades and replatforming.

Sitecore

How we improved page load speed for Next.js ecommerce website by 50%

Sergei Pestov

How to stop declining of the performance indicators of your ecommerce website and perform optimising page load performance.

Next.js

Sitecore integration with Azure Active Directory B2C

Dmitry Bastron

We would like to share our experience of integrating Sitecore 9.3 with the Azure AD B2C (Azure Active Directory Business to Consumer) user management system.

Sitecore
Azure

Activity logging with Xperience by Kentico

Dmitry Bastron

We'll dive into practical implementation in your Xperience by Kentico project. We'll guide you through setting up a custom activity type and show you how to log visitor activities effectively.

Kentico

Interesting features of devtools for QA

Egor Yaroslavcev

Chrome DevTools serves as a developer console, offering an array of in-browser tools for constructing and debugging websites and applications.

Devtools
QA

Kentico replatforming and upgrades

Anastasia Medvedeva

Since 2015, we've been harnessing Kentico's capabilities well beyond its core CMS functions.

Kentico

Umbraco replatforming and upgrades

Anastasia Medvedeva

Our team boasts several developers experienced in working with Umbraco, specialising in development, upgrading, and replatforming from other CMS to Umbraco.

Umbraco

Sitecore Personalize: tips & tricks for decision models and programmable nodes

Anna Gevel

We've collected various findings around decision models and programmable nodes working with Sitecore Personalize.

Sitecore

Fixed Price, Time & Materials, and Retainer: How to Choose the Right Agreement for Your Project with Us

Andrey Stepanov

We will explain how these agreements differ from one another and what projects they are suitable for.

Customer success

Enterprise projects: what does a developer need to know?

Fedor Kiselev

Let's talk about what enterprise development is, what nuance enterprise projects may have, and which skills you need to acquire to successfully work within the .NET stack.

Development

Headless CMS. Identifying Ideal Use Cases and Speeding Up Time-to-Market

Andrey Stepanov

All you need to know about Headless CMS. We also share the knowledge about benefits of Headless CMS, its pros and cons.

Headless CMS

Dynamic URL routing with Kontent.ai

We'll consider the top-to-bottom approach for modeling content relationships, as it is more user-friendly for content editors working in the Kontent.ai admin interface.

Kontent Ai
This website uses cookies. View Privacy Policy.