This guide is intended to help our software development teams create scalable, maintainable, and efficient systems that meet our client's needs. It is a reference document for our engineers to follow as they work on various projects.

Modularity

We design our systems to be modular, which means that each component should be independent and loosely coupled. This makes it easier to maintain and scale our systems. A good example of modular code is a web application that is built using a modular architecture.

<aside> 💡 For example, please refer to our open-source whisper-chain-be repository. The whisper-chain backend is divided into modules and very clearly structured under services, libs & helpers.

</aside>

Scalability

We design our systems to be scalable, which means that they should be able to handle increased traffic or usage. We must use techniques such as load balancing and horizontal autoscaling to achieve this. For example, the whisper chain application leverages on

Reliability

Our systems should be reliable, which means that they should be able to operate continuously without downtime. We must use techniques such as Blue/Green deployment, redundancy and failover to achieve this.

Integration

Our systems should be able to integrate with other systems or services. We must use techniques such as APIs and message queues to achieve this.

<aside> 💡 Example of Scalability, Reliability & Integration done the right way -

Fab, an e-commerce store that our team engineered, needed to be integrated with our in-house Warehouse Management System’s shipping service to automatically generate shipping labels and track shipments. To achieve this, we used the following techniques:

  1. APIs: The shipping service exposed an API that our e-commerce store can use to programmatically create shipments and track packages. Our website's backend code would call the REST APIS, passing in the necessary information such as the customer's address and order details. The shipping service would then respond with a shipping label or tracking information, which our website can use to update the order status and provide tracking information to the customer.
  2. Message Queues: To ensure that shipping requests are processed in a timely and efficient manner, we used Redis as our message broker. When a customer placed an order on our website, our backend code would add a message to the shipping queue, containing the necessary information to create a shipment. The shipping service would then consume messages from the queue, processing each request in the order it was received. This approach ensures that shipping requests are processed in a scalable and reliable manner, even during periods of high traffic or system load.

By using APIs and message queues to integrate our e-commerce store with the shipping service, we automated the shipping process and provided a better experience for our customers, while also ensuring that our systems are scalable and reliable. We ended up shipping 24000 orders a day.

</aside>

Flexibility

Our systems should be flexible, which means they should be able to adapt to changes in requirements or customer needs. We must use techniques such as microservices and APIs to achieve this.

<aside> 💡 Example -

Let's say you have an online marketplace that allows users to buy and sell products. Initially, your website only allows users to sell physical products, but you later decide to add support for digital products such as e-books and software downloads. To achieve this, you would use the following techniques:

  1. Microservices: Instead of building a monolithic application that handles all aspects of the marketplace, you would break it down into smaller, independently deployable microservices. For example, you might have one microservice for handling product listings, another for processing payments, and another for delivering digital downloads. By breaking the application down into smaller, focused services, you can more easily make changes to individual parts of the application without affecting the entire system.
  2. APIs: To allow the different microservices to communicate with each other and with external systems, you would use APIs. For example, the product listings microservice might expose an API for creating and managing product listings, while the payments microservice might expose an API for processing payments. By using APIs, you can create a flexible system that can adapt to changes in requirements or customer needs, without having to rewrite large portions of the application.

By using microservices and APIs to create a flexible and modular architecture, you can easily add new features and functionality to your marketplace, without disrupting existing functionality or requiring extensive code changes. For example, if you later decide to add support for a new payment method, you can simply create a new microservice for that payment method and integrate it with your existing payment processing microservice using APIs. This approach allows you to quickly adapt to changing customer needs and stay competitive in a fast-paced marketplace.

</aside>

Monitoring and logging

We should monitor our systems to detect and resolve issues quickly. We should use techniques such as logging and alerting to achieve this. All our in-house products must have a logging lib and use it appropriately.