Posts

Showing posts with the label SOA

AI Agents and Distributed Monoliths

Image
Distributed Monoliths are a significant source of technical debt and a major anti-pattern. Distributed monoliths have the worst of both monoliths and Microservices . It's very easy to create distributed monoliths because often people don't learn proper principles, and mistakes keep happening over and over again. Distributed Monoliths are everywhere: on DevOps solutions , on the Frontend , even in Data . Why? Because we still don't add proper isolation in systems. Now Distributed monoliths will happen with AI and Agents or "Agentic" solutions. Let's understand what's going on and how we can protect ourselves from another disaster.

State

Image
If you look up on dictionary.com the first two definitions of state are: the condition of a person or thing, as with respect to circumstances or attributes: a state of health. The condition of matter with respect to structure, form, constitution, phase, or the like: water in a gaseous state. Software is all about data, which is the state. The state could be your basic data, such as your name, last name, address, phone, email, bank account ID, or any other IDs and information you might have. Buying software has many side effects, many of which  are negative . Such data needs to be captured somewhere, usually in a relational database. But it could be in any other data store like a NoSQL Database like Cassandra, a K/V store like Redis, or an object store like S3. Ideally, the state should be contained and even isolated. However, in distributed systems, we often need a distributed state. The state is necessary. However, we might create additional complexity if we don't deal with the s...

Leaky Contracts

Image
Service contract design is hard. People do it all the time, but it is not always correct. Most of the time, engineers pay more attention to the service's internal implementation than the contract. A Service contract is the most important part of a service. A good contract provides an abstraction that allows us to have flexibility and allow future refactoring without impacting clients. Being able to refactor code without breaking consumers is pure gold. It's priceless. Not all industries are the same; however, the more dynamic and agile the industry is, the more you need to be able to do Refactoring. To do refactoring more often, you need to make decisions that allow refactoring to happen at a lower cost. If the price of refactoring is always high, no refactoring will happen, and that is game over; that is how we create inadequate legacy systems. A service contract provides a high level of abstraction(ideally) or might(if they do a poor job) leak internal implementation details....

Services

Image
We are in the holiday season. You walk into any Starbucks and see the Christmas decorations. Lights and Christmas trees are everywhere, and the advent of code is still rolling. Whether Xmas is summer or winter, You can get some specials and flavors only on Xmas. Now, you must wonder if this is a technical blog post; yes, 100% it is. I promise there will be a point at the end. Let's imagine a very different coffee shop experience; in reality, it's not how I will describe it, but hopefully, it will help you to see my point. I'm pretty sure you've gone to a coffee shop before; how it works is simple: you look many for what coffee + snacks you want, you get in line, pay at the cashier, and then the barista will brew you coffee, warm your food, and you will be good to go. If it is a good place, they will call you by name. Now, let's imagine a very different experience. Consider this the upside-down Xmas experience. However, if you want to name it, I will give you my nam...

Proprietary Systems and Distributed Monoliths

Image
Distributed Monoliths are the predominant form of modern legacy systems. Sometimes distributed monoliths are created by teams misapplying microservices architecture due to lack of isolation or internally shared libraries break of isolation. Other times, there is just the proverbial no time to refactor. Let's share the database. However, sometimes distributed monoliths happen due to non-obvious reasons from decisions that, at first glance, sound like good ideas and are even far away from engineering.  In software, we often run a trade-off analysis, Build vs Buy, where we must decide whether to build or buy software. Buying is usually attractive because it gives some speed (since you don't need to code it). Building, of course, takes longer, and you will need to maintain it; there is a chance of the project failing, and you invest money and have no software. There are trade-offs between building and buying. However, people often think buying has no implications and is much better...

My third book is out: Continuous Modernization

Image
After 7+ months of hard work, my third book is out. Introducing:  Continuous Modernization : The never-ending discipline of improving microservices, monoliths, distributed monoliths, individuals, and teams at scale. Modernization is something I have done over and over in my life. Modernization is something that all companies need and will always need. The need for modernization will never go away, even with LLMs and AI. Technical debt, Anti-patterns, and bad decisions do not take days off. Complexity never shirks and continually grows. Companies do not stop getting bigger and doing more and more software critical to growth, delivering value to customers, and staying competitive and relevant in the market. We need a better way of doing software to drive the best outcomes out of us. Continuous modernization is the counterforce to technical debt and anti-patterns. Continuous modernization is how to continually improve, even when you think it's impossible and nothing can be done. We ca...

Proper Error Handling

Image
No matter what programming languages you use. Engineers need to make dozens to hundreds of small decisions every day. Such decisions can sometimes save us and, other times, create many problems. Some of these decisions can be called assumptions. Depending on the context, they could be the side-effect, lack of proper discovery, feature factory rushing to delivery, or lack of care. In reality, error handling is one of the most challenging things in computer science, alongside naming, cache invalidation, and off-by-one errors. We usually get error handling wrong. When we are supposed to throw an error/exception and crash the application, we are unlikely to return some bad, sneaky default that will produce a bug down the road; when we need to ignore missing information, we end up crashing the app. Code reviews rarely to never review error handling. It's common to see services in production that don't even have the proper exception track due to improper error logging. Error handling...

Service Chain

Image
Services are a very important architectural construct. Proper services( POSAM definition and principles) are even more important. However, not all services are the same. Not all APIs are the same, and definitely not all services are the same. Just having a Service or API, we can call it many different ways; the question is how good it is and how solid it is. I still put my money where my mouth is and say that services are a very powerful concept and the right level of abstraction for most problems. However, when a service is presented to you, you cannot assume you will have high quality just because it's a service. IF services are desired, multiple services must still be desired; after all, service orientation is about having services, not libraries. However, we know that when the granularity is wrong, and when we move data and capability to the wrong places, let's say, the wrong domain, we make things worse, not only risking breaking isolation but also leading to wrong abstra...

My second book is out: Principles of Software Architecture Modernization

Image
After 1+ year of hard work, my second book is finally out. Introducing: Principles of Software Architecture Modernization: Delivering Engineering Excellence with the art of fixing microservices, monoliths, and distributed monoliths. I've 20+ years of experience with technology and have been an architect and a technology consultant for most of this time, software architecture is a deep passion of mine. It is a huge pride and joy, for me to come here today to share this with you, my friends, and dear readers. 🎉🎉🎉 I deeply appreciate all the blessings God has given me, from my family, my daughter Clara, my wife Andressa, my work, and my friends. It was not easy to write this book 📘, there was sweat, blood, and tears, lots of remote work with my co-author Sam . Rest assured you are getting my passion, vision, and perspective of software architecture. First and foremost the book is about principles, tradeoffs, and software architecture design at the heart of complexity. The book is ...

Embedded Mocks and Hidden Contracts

Image
Testing is essential . Testing requires diversity, from integration to chaos , from your local machine to production . Writing tests not always is fun because sometimes is hard to write tests because not all contracts are good, and clean and went through a lot of thought processes. Is easy to blame the design, architecture, and even the implementation, but are we sure we are not missing anything? Something that is hard to test very likely will not be tested. Testability is a good property of any design or architecture sure. Making good solutions that are easy to test is a good thing. However, mocking is often taken for granted, meaning is seen as something that is just good and has no drawbacks, but that is not true. Everything has drawbacks. Integration tests are often seen as bad practices and people tend to lean toward unit tests instead. Just keep in mind Integration tests don't require mocks. Unit tests often require mocks to keep them isolated and cut off external dependencie...

Distributed Monolith

Image
Distributed Monoliths are the worst. Nothing good comes from distributed monoliths. No one wants to have distributed monoliths, and still, they are very common in the industry. Complexity just gets bigger, our industry just gets more and more entangled. Complexity has everything to do with distributed monoliths. Distributed Monoliths are very complex, much more than monoliths. How can you avoid a trap? By definition, the only way is not to follow into the trap. Understanding the trap is how you can avoid it. However, some traps cannot be avoided because there are bigger forces like acquisitions, pandemics, economic downturns, wars, or time. Time can easily be the biggest trap of all. We need to learn how to work effectively with monoliths and distributed monoliths because they are to stay and we can't ignore them. Fishing monoliths is a long-turn battle, that requires persistence, patience, and allies. Let's start by understanding monoliths and Distributed Monoliths a bit more.

Proper SOA Isolation: The 3 frontiers

Image
  Building service is easy. Isolating that service, it's easier said than done. Anyone can build any service with any technology or stack. However, would this service last, or will it become technical debt? Many organizations trying to go all in with microservices end up with distributed monoliths instead of isolated services. The result is more complexity, less business value, and slower lead times. We had many movements and many different technologies and styles of architecture in our industry. From SOA, Soap, ESBs, BEPL, REST, Event-Driven, gRPC, GraphQL, Microservices, and Serverless, we still cannot get services right - did you wonder why? IMHO it's all about principles and isolation is at the CORE of everything. Software will get more complex at Scale, and change will always happen. The question what are you doing to be more anti-fragile? Proper services require thinking and proper architecture and design principles applied at all times during a service SDLC.

Configuration Ownership

Image
  Building software at scale is tricky, and when you have lots of software, you have more problems to solve. Several times engineers look for ways to make their lives easier: make it simple, transparent, and easy to use. That sounds like a good idea, right? What can go wrong with that? Typing is never the bottleneck and will never be. We are all obsessed with reuse; several times, the reuse is marginal and brings way more problems than benefits. Working with an Object-Oriented Language such as Java makes a lot of sense to leverage Dependency. Injection and Ioc(Inversion of Control). Because it's easier to test the Application and also easier to change the Code. In the past, Spring Framework was all about XML; today, all configuration is pretty much done via Code. It's possible to use property files to configure some aspects of backend services written in Java with Spring, yes, but in reality, most of the Code is in the Code in the form of Java Spring Beans.  Spring Framework ...

Tolerant Reader Pattern

Image
Reading and writing configs and objects can be more challenging than it looks. As your application evolves and your contract is used across several services, you might need to have Backward Compatibility. Easily we can think about 2 scenarios, the first scenario let's say you have a distributed monolith and you have multiple apps using the same database. The second scenario considers you have an Event Sourcing + CQRS application using Kafka for instance where you emit and read domain events. In both scenarios, there will be breaking changes, so how we can make your parsers and serializers to be more efficient and resilient to change, well: The Tolerant Reader Pattern is here to rescue.

Strangler Pattern Done Wrong

Image
Some years ago, every backend engineer wanted to be doing microservices . There was absolute hype. A vast majority of the market joined the microservice bandwagon without previous expertise in SOA. Some companies were successful. Still, several companies ended up in the worst place they were before. Therefore we see the Death of Microservices . IMHO there are many reasons why that happens to name a few: Lack of proper architecture skills in SOA , Lack of Isolation, Lack of Analysis, and jump to solutions too fast. Once you start distributing code across several code bases with multiple contracts, it is better to be correct because the rollback is a multi-year migration project and not easy to sell. How does that kind of thing happen exactly? In Microservices, the way to go is to use the Strangler Pattern, however by applying the pattern in the wrong way, thats where we arrive at the worst outcome: A distributed monolith. 

Threadcast: A morte dos Microsserviços com Diego Pacheco

Image
Normalmente eu nao blog em português, mas hoje quero compartilhar um programa que participei recentemente. Programa gravado com o Inacio da South System sobre Arquitetura de Software, mais especificamente falando de Microservices, SOA, Shared-Libs e bem como os problemas e as soluções. Microservices estão em baixa nos dias de hoje. Porém muitas vezes não entendemos por que estamos usando microservices e nem por que estamos parando de usa-los. Muito difícil conversar sobre SOA e microservices sem falar de shared-libs e o impacto nessas arquiteturas. Nessa conversa você ira entender mais os problemas desse landscape bem como muitas alternativas para editar esses problemas. Entao bora la ver esse video! 

It's all about Contracts

Image
SOA(Service Oriented Architecture) is all about contracts. Contracts can either be managed explicitly by doing Contract First, Customer-Driven Testing, having POs manage the contract as an important asset as much as a UI is. Contracts can also be unmanaged or managed implicitly just pushing problems to consumers and making the whole org move slowly. So what is a contract anyway? Why should we care?  The contract is all Data, Behavior, and expectation involved in the services capabilities. It's easy to see just the endpoint's input and output data and forget about the rest. The rest is smaller things like data formats, access protocols, serialization formats, and do not forget about expectations. For instance let's say you are returning a list of customers, if the data is in ascending or descending order it might affect your consumer code or tests.  Contracts cab be versioned and we should have specific tests on the Implementation provider side in order to make sure we don...

Testing AWS Lambdas with Java

Image
AWS Lambda is an awesome Serverless implementation. Lambdas are a bit tricky because they are ephemeral and short-lived so either they call another lambda or they will mutate some external state. Either an external data store like RDS, Aurora, S3, Kineses, Elasticache or they will call another microservices that does state mutation. In order to properly test Lambdas, we need to design for testability, the easier thing to do is always create more lambdas because you can check the input and output. So lambdas are not pure functions(functional programming) they often need to have side effects. So AWS has this library that makes it easier to test lambdas for Unit Testing / Mocking but also for localized Phased Integration Tests. You can mock source events like S3 ones, and also mock the context, and just test your lambdas with Junit. So I made a simple POC and video I want to share with you guys. So Let's get started!

Spring-Boot Native Image

Image
Spring Boot is the most popular java stack nowadays. New languages like Go and Rust are capable of creating a single binary, self-contained with all deps to run the application. This is great for deployment simplicity but also easier to maintain. As time pass we want to have fast bootup times and do more with less. The native solutions are fast since they are statically compiled for a target platform or OS(in the case of UniKernels). Java was designed to be better as time pass(Runtime) and optimizations kick in. However thats not ideal for Serverless applications. GraalVM changes that since allowing us to compile JVM applications(Java, Scala, Kotlin) to native applications. Today I want to share a simple Video + POC using a new project called Spring Boot Native which allows us to create native images to spring boot apps.  Native images have some challenges like Type Erause for C++ and Reflections in Java. So Let's get started!

Java SPI

Image
Java SPI is a standard java way to have binding between contracts and implementations. SPI used for several use cases such as Currency, Locale, TimeZone, DateFormat, Number, JDBC Driver, JPA, Json, JasonB, and many more. I believe the most classical example is for JDBC/JPA use cases where you have one common spec(contract) and multiple implementations for each database driver such as MySQL, Postgres, etc... SPI is interesting, shower I would not use SPI for common bread a butter SOA / Microservices use cases. Because often you just have one contract and one implementation, for that case using the new keyword or even basic DI/IoC I would say is much more desirable, easier, and much more simple and straightforward. However, if your use case has multiple implementations(beyond versioning) thats definitely something you should consider.