Adapting to Constraints: understanding their impact and turn them into opportunity

Giulio Rusciano
6 min readAug 4, 2023

System constraints refer to non-negotiable limitations that provide a foundation for our software architecture. They are often considered as the pillars of the architecture since they shape and guide the design of the system.

Unlike functional requirements that specify what the system must do, constraints limit how the system can be built. Therefore, they play a crucial role in defining the boundaries within which the system can operate.

Understanding the system constraints, we gain a better understanding of the design space available to us and the trade-offs we need to make to deliver the required functionality.

To put in other way, a system constraint is a predetermined decision that limits our freedom to design the system. While it may seem like a negative aspect, constraints can also be beneficial by providing a starting point or narrowing down the options for the architecture. Instead of seeing constraints as a limitation, we can view them as a guiding principle that makes our job easier by streamlining the decision-making process.

There are three types of constraints that typically we must take into account:

  • technical constraints;
  • business constraints;
  • legal constraints.
Photo by Nicolas Gras on Unsplash

Technical constraints

As software engineers, technical constraints are a common occurrence in our daily work, so it’s a familiar concept. These constraints can arise from a variety of reasons such as existing contracts or security policies which restrict us to a particular hardware or cloud vendor, in-house frameworks built with a specific programming language or the challenge of finding skilled engineers for different languages, specific databases or technologies required for compatibility reasons, and being mandated to support certain platforms, browsers, or operating systems due to licensing, support costs, or client preferences. However, this list is by no means exhaustive it is a good representation of technical constraints we could be take into account in our professional activities.

On the surface, technical constraints may all seem like they belong to the realm of implementation and not the software architecture. In fact, they often have a significant impact on our software architecture decisions. Technical constraints may dictate the choice of programming language, infrastructure, or third-party libraries, which in turn affects the architecture decisions such as the choice of patterns, components, or modules.

Let’s take the example of a company that has decided to support older browsers or low-end mobile devices that don’t support certain communication protocols or can’t handle as much data. That choice can significantly impact our software architecture and we may have to make significant adjustments to accommodate these platforms and their APIs while providing a more high-end experience for newer browsers or higher-end devices. This can result in a more complex architecture, which may require additional effort to maintain and may affect the overall performance and scalability of the system.

Business constraints

As software engineers, our primary focus is on making sound technical decisions and choices. Nevertheless , we often have to take into account constraints from our business team that require us to make trade-offs in both architecture and implementation. Our job is to incorporate those requirements into our architecture and take the necessary decisions accordingly. This involves carefully balancing technical feasibility with business priorities and working collaboratively with our business partners to ensure that the final product meets expectations both on technical and business side.

For instance, when often faced with a business constraint such as a tight budget or deadline, we have to make different decisions than if we had unlimited resources. Needless to say that some software architectural patterns are better suited for small startups that need to quickly launch a product with a limited team, while other patterns are more appropriate for larger organizations with more engineering teams and a larger budget.

Besides time and budget limitations, business constraints can also dictate the use of third-party services as part of our architecture. For instance, if we’re developing an online store, we might focus on providing a seamless shopping experience for our clients while relying on third-party providers to handle shipping and billing.

Legal constraints

The third type of constraint originates from various regulations and rules, which may be global or specific to a particular region. For instance, if we’re building a system that deals with medical information or patient records in the US, we must comply with the HIPAA regulations that place constraints on who can access the patient data and the security measures needed to protect sensitive information. Similarly, in the European Union, GDPR imposes limitations on what data online services can collect, store, and share with third parties about their users, as well as the duration for which data can be retained.

Other regulations may also regard adherence to specific accessibility standards as a legal constraint: In many countries, accessibility standards are legally mandated for certain industries or organizations. For example, the ADA in the United States, the AODA in Canada, the EAA for Europe and so on.

Therefore, depending on the industry and the country where our services will be offered, we may face different regulatory constraints that affect our system’s architecture.

Real or self-imposed?

To effectively manage constraints, we need to keep two considerations in mind. Firstly, we should not take any constraint lightly, as it may have significant implications on the architecture and implementation of our system. It is important to differentiate between real constraints that are outside our control, such as regulatory requirements or limited resources, and self-imposed constraints that we can negotiate or eliminate.

For instance, when dealing with external rules and regulations, we may have limited room for negotiation. However, in case of budget and time constraints imposed by our business, we can discuss the possibility of extending the deadlines or stretching the budget. Similarly, if we are tied to specific hardware, cloud vendors, or technologies, we can use this opportunity to explore other options that can potentially benefit our business in the long term.

If we agree to take on a set of constraints,, it’s very hard to back away. If we later discover that those constraints were not actual limitations, our overall architecture could become ineffective or even nonfunctional.
It is therefore crucial to carefully evaluate the constraints presented to us and determine whether they are truly necessary before making any significant decisions.

Loosely coupled: keep the system as flexible and adaptable as possible

This brings us to the second consideration which is that when we do take on certain constraints, we need to leave enough room in our architecture to move away from those constraints in the future. For example, if we are limited to a particular database that we need to use or some third-party service that we have to integrate with, we need to make sure our system is not tightly coupled to that particular technology or those specific APIs. And if in the future, we are able to use different technologies or different services, we will need to make minimal changes instead of re-architecting the entire system from scratch. When we get to the topic of architectural building blocks, we will see many examples of specific tools and general techniques on how we can decouple different parts of the system in a way that they can be easily replaced or updated independently without the need to refactor the entire system.

For instance, if we’re restricted to a particular database or third-party service, we should avoid tightly coupling our system to that technology or APIs. This approach enables us to replace or update them with minimal changes, without needing to rebuild the entire system from scratch.

In conclusion

In this article, we discussed the importance of system constraints as the third architectural driver and type of requirement alongside with functional and non-functional (quality) requirements. We learned to view them as a guiding principle that makes our job easier by streamlining the decision-making process. We classified the types of constraints based on their sources and explored how they have a significant impact our software architecture. We also covered some essential considerations we need to keep in mind while dealing with this kind of constraints:

  • are the constraint real or are negotiable? Can we consider the constraints we have as an opportunity to that can potentially benefit our business in the long term?
  • In evaluating the options we have for our system architecture are we keeping the system flexible in order to move away from those constraints in the future?

Don’t miss out! Remember to follow and share this post for maximum impact.

Your support means the world to me and can make a real difference in reaching people who would enjoy reading this story.

As I conclude, I want to express my gratitude for your valuable time. Thank you and have a wonderful day!

What to read more about system requirement? here another articles that may interest you: System Requirements and Architectural Drivers, key factors for successful architectures



Giulio Rusciano

20+ yrs in technology leadership, design, development & entrepreneurship, I'm a creative technologist who blends design & tech to bring innovative ideas to life