#software architecture
20 posts

Advice from a GraphQL Expert

GraphQL is a great query language to speed up client development. As a backend developer, you are no longer under pressure to build APIs specific to niche use-cases that client's demand.
Read more

Advice from a GraphQL Expert

GraphQL is a great query language to speed up client development. As a backend developer, you are no longer under pressure to build APIs specific to niche use-cases that client's demand. This post addresses some great advice from, Francesca Guiducci, a GraphQL expert.

  • Evaluate if GraphQL fits into your architecture. It can front a database and even a REST API.
  • Involve other people while designing the schema. The schema is your source of truth and needs to be well thought out.
  • Change your mental model to think in graphs. Most data is relational in nature, GraphQL schemas must be modeled to represent that relation.
  • Make the schema easy to evolve. Since GraphQL versioning is frowned upon, leverage keywords like @deprecated to evolve the schema. As far as possible, be forward thinking while constructing your schemas.
  • Be intentional while incorporating nullability into the schema. This leads to cleaner and simpler architectures.
  • Since pagination isn't implemented natively in GraphQL, design this carefully and incorporate it from Day 0. Reduces a lot of heartburn in the future.

Full post here, 9 mins read

Data-oriented architecture

In data-oriented architecture (DOA), systems are organized around small, loosely coupled components that are always stateless and component-to-component interaction is minimized so that they interact through a data layer instead.
Read more

Data-oriented architecture

  • In data-oriented architecture (DOA), systems are still organized around small, loosely coupled components as in services-oriented architecture with microservices. However, the components are always stateless and component-to-component interaction is minimized so that they interact through a data layer instead.
  • Common examples that approximate DOA include those using data monoliths where all or most data is persisted in a single store, such as knowledge graphs or GraphQL.
  • If you are worrying about scaling your architecture horizontally, you can consider a data monolith at its center and base your decision on these factors:
  1. Service-to-service APIs are not necessarily ad hoc, but it is easier to pass parameters in direct component-to-component communication.
  2. Beware if your system has integration as a bottleneck, as it will affect growth.
  3. Think hard about data ownership: multiple writers might have to modify the same record so you need to partition write ownership.
  4. Carefully plan the shared global schema because inter-component APIs are encoded in the data.
  5. If services call others with a direct address (like an IP) and know where to reach a particular service from command-line parameters, you need to wrap those better to construct the right flags, depending on the environment (say, structuring each service under a path routed by one server).

Full post here, 10 mins read

The cracking monolith: the forces that call for microservices

Overweight monoliths exhibit degrading system performance and stability, or slow development cycles, or both.
Read more

The cracking monolith: the forces that call for microservices

  • Overweight monoliths exhibit degrading system performance and stability, or slow development cycles, or both.
  • Single points of failure are typical of large monolithic apps and when they come under pressure, your team spends too much time solving technical issues instead of on development. For example - outages in non-critical data processing that bring down the whole system. Or all time-intensive tasks grouped into the background and becoming so unstable as to need a dedicated team. Or changing one part of the system affects others that should logically be unrelated.
  • If shipping a hotfix takes weeks or months, you will have a problem with slow development. To know when it is a good time to break the monolith, you should watch out for:
  • CI builds that take longer than 10 minutes (though a good CI tool should help it by splitting or auto-sequencing tasks).
  • Slow deployment, due to many dependencies and multiple app instances, especially when containerized.
  • Slow onboarding of new staff as it may take them months to get comfortable enough to make a non-trivial change to the codebase. Veteran team members becoming a bottleneck as reviewers because too many developers are waiting for their inputs.
  • New use cases and problems are not easily addressed with existing tools, and software updates are being put off, indicating you are dependent on outdated technology.

Full post here, 6 mins read

Breaking down a monolith into microservices - an integration journey

Avoid too much decoupling as a first step, you can always break it down later on. Enable logging across the board for observation and monitoring.
Read more

Breaking down a monolith into microservices - an integration journey

  • Before transitioning, identify the biggest pain points and boundaries in the monolithic codebase and decouple them into separate services. Rather than the size of code chunks, focus on ensuring these services can handle their business logic within the boundaries.
  • Split developers into two teams: one that continues to work on the old monolith which is still running and even growing and another to work on the new codebase.
  • Avoid too much decoupling as a first step, you can always break it down later on. Enable logging across the board for observation and monitoring.
  • Enforce security between microservices with mutual TLS to restrict access by unauthorized clients even within the architecture, and Oauth2-based security service.
  • For external clients, use an API gateway for authentication and authorization, and firewalls and/or tokens based on the type of client.
  • Secure any middleware you use as most come without credentials or a default credential. Automate security testing in your microservices deployment procedure.

Full post here, 5 mins read

Adopting microservices at Netflix: lessons for architectural design

Create a separate data store for each microservice and let the responsible team choose the DB that best suits the service.
Read more

Adopting microservices at Netflix: lessons for architectural design

  • Create a separate data store for each microservice and let the responsible team choose the DB that best suits the service. To keep different DBs in sync and consistent, add a master data management tool to find and fix inconsistencies in the background.
  • Use the immutable infrastructure principle to keep all code in a given microservice at a similar level of maturity and stability. So, if you need to add or rewrite code for a service, it is best to create a new microservice, iterate and test it until bug-free and efficient, and then merge back once it is as stable as the original.
  • You want to introduce a new microservice, file or function to be easy, not dangerous. Do a separate build for each microservice, such that it can pull in component files from the repository at the appropriate revision level. This means careful checking before decommissioning old versions in the codebase as different microservices may pull similar files at different revision levels.
  • Treat servers, especially those running customer-facing code, as stateless and interchangeable members of a group for easy scaling. Avoid ‘snowflake’ systems where you depend on individual servers for specialized functions.

Full post here, 7 mins read