A lot of technologies, practices, and architectural patterns have emerged over the years — and one of these is the microservice architecture, which we’ll dive into in this episode of cocktails.
Joining us today is one of the authors of the popular book “Fundamentals of Software Architecture”, and we discuss whether microservices are evolutionary or revolutionary, the major hurdles of trying to implement this architecture, and discover why there really aren’t any “best practices” when it comes to software architecture.
Kevin Montalbo: All right. Joining me all the way from Australia today is TORO Cloud’s CEO and Founder David Brown. How are you doing, David?
David Brown: Good, thanks Kevin.
KM: And our guest for today is an experienced and hands-on software architect involved in the architecture design and implementation of microservices architectures, service-oriented architectures, and distributed systems in a variety of technologies. He has significant experience and expertise in application integration and enterprise architecture, which is all found in Developertoarchitect.com - a free website he founded devoted to helping developers in the journey to becoming software architects.
Apart from this, he's also the author of numerous technical books and videos, including the "Fundamentals of Software Architecture", "Software Architecture Fundamentals" video series, and several books and videos on microservices, as well as enterprise messaging. In addition to hands-on consulting, he's also a conference speaker and trainer, having spoken to hundreds of conferences and user groups around the world on a variety of enterprise-related technical topics.
And he can now proudly add Coding Over Cocktails to one of those speaking engagements. Ladies and gentlemen, joining us for a round of cocktails is Mark Richards. Hi Mark, how have you been doing?
Mark Richards: Hi Kevin! Fantastic. I'm doing great. And thank you so much for having me on this podcast. This is exciting. I love the name "Coding Over Cocktails." I'm assuming that that is only for those that are listening and not for those speaking. So, I am appropriately having tea and that will be my cocktail for today.
DB: We have been known to bring a cocktail on the show. It depends on the time of the day.
KM: I'm personally having coffee because it's seven o'clock in the morning here in the Philippines. All right. So, thank you very much, Mark, for being with us. Let's dive right in.
So, last December, you tweeted about your controversial O'Reilly keynote, where you stated, and I quote, "There are no best practices in software architecture." I think this forms a major theme of your book, "Fundamentals of Software Architecture" with Neal Ford. So can you tell us more about how you came up with that conclusion? Why are there no best practices in software architecture?
MR: Boy, Kevin, did I get into a lot of heated debates with that comment. As a matter of fact, that was during the keynote at O'Reilly's Software Architecture Conference last February - almost a year ago. And that was February, 2020. And I like to do keynotes in two forms - one is to inspire; the other is to incite. And this one seemed to actually do both. Yes, as a matter of fact, that phrase was very bold to say and I'm so glad, Kevin, you asked that question because I want to qualify it, because it did create quite a lot of controversy on a lot of social media immediately after making that statement.
The crux of it, really, came from two laws of software architecture that both Neil Ford and I coined in our book, "The Fundamentals of Software Architecture", and that first law of software architecture that we coined was that everything in software architecture is a trade-off. And that was the first law. The second law, which really doesn't relate to it, but still I'll mention is that the "why" is more important than the "how". And this was one of our epiphanies that when you're describing an architecture, what's most interesting is why you made a certain choice. I could see how it works, but I don't know. I can't read your mind. But let me come back to that first one, because it was a fairly bold statement to say based on our first law - which by the way, no one has ever refuted - that everything in software architecture is a trade-off. I went further to say, "What this infers is that there are no best practices in software architecture."
And let me give you a couple of examples where this came from, and then I can kind of qualify it for you. Because whenever we're doing any kind of thing in architecture, structural architecture, you can't say, "Oh, well you should always focus on performance," or, "Oh, you should always split those services up." "Anytime you have a service that does three things, split it into three." You can't make these statements because of our first law of software architecture. I could probably spend a half an hour actually going through examples where everything's a trade-off. And that's why we always say - it depends every time we get a question, it depends. However, I do want to qualify this because I've had a lot of very constructive and interesting conversations with a lot of people on social media and also just on Zoom and phone calls about this. And I will qualify to say, within the structural aspects of software architecture, there are no best practices because every environment, every situation, is different and you can't say, "Oh, you should always do this."
However, I will concur within another aspect of software architecture, which is architecture, the process, there are in fact, some best practices. Always collaborating, communicating with a stakeholder. There's a good best practice. Always do that. Here's a good one - always analyze trade-offs, which is kind of meta because it actually confirms our first law of software architecture. So I had to soften my tone a little bit on that and really focus it more on the structural aspects because I do concur that there are in fact, the best practices in the process of creating architectures. But yes, that was quite an interesting keynote. It really stirred the pot, which is what I believe keynotes are supposed to do. It's what makes them exciting.
DB: Mark, you said it incited a response as intended. What were the major objections?
MR: The major objections were, in fact, it was to bullet a statement that in fact there are best practices in architecture. And the problem, David, was that when I made that statement, I wasn't really encompassing both aspects of software architecture. And when we think and try to define software architecture, it's really hard to define. And one of the good ways of really getting an understanding and trying to define software architecture is to think about it, really, as two different aspects - architecture, the structure - and that's more of the technical architecture. When we start talking about cohesion and coupling and connascence, and all these technical details about structuring our code and our services, that's the structural aspect. And I still do maintain by the way, David, that there are no best practices in the structural aspect. It always depends.
But the process aspect, what you're referring to now, in fact is one way I try to define software architecture and surprisingly enough, David those were where the arguments ended up occurring. And it's like, "No, what about communicating with stakeholders?", "What about appropriate documentation?", "What about this?", I'm like, "Ooh, yeah." You know, "What about collaborating with teams?", and I'm like, "Whoa. Yeah, you're right." And I’m like, "Ah. I see where my mistake is."
DB: You came up with this original concept. How do you distinguish between structure and process?
MR: Structure is when we start applying technical aspects to how our code, our source code is organized. Is it a one large monolithic application that's deployed as a single unit, such as the layered or a monolithic?
DB: My thought is when you came up with this statement, "There are no best practices…", had you distinguished between "There are no best practices in structural design as opposed to process design?" or was that a distinction you made after you stirred the pot and got all this debate going? And how did that work out?
MR: You know what, David, this is what I absolutely, positively love about conferences and what I miss so much about speaking at them live, because without doing this, you don't get the feedback. Yes, in fact, both Neal Ford and I did consider the techniques and soft skills aspects as well. Let me give you a really good one; the use of architecture decision records. I love architecture decision records. It's a way of recording and documenting the architecture, but recording the "how", or I'm sorry, recording the "why". But I can't say that that's a best practice. I really like using them. I find them extremely effective, but you, David, may not, and your environment may not be conducive to the type of documentation that you might need that is lacking in an architecture decision record. So how can I say and claim that that's a best practice?
So we did analyze a lot of the process aspects, however Neal and I fed off each other. We really didn't have that live bulk feedback that you get from these conferences and making these statements. So the nice thing I can actually say about this is, I am not at all, sorry that I made that statement in that keynote, because it spawned a lot of healthy communication and examples here and there where all of us actually learned. And that's really the key. I think, David, is the fact that we make these statements and especially if they incite something or they're a little bit controversial, what it does promote is conversation. And that's where the learning comes from, in my opinion. And so I did learn something from that conference that we didn't take into account all of the process aspect of architecture in that kind of bold statement. However the statement that there are no best practices was my interpretation of our first law. And so that's where kind of, I stepped a little over the line there and like I said, I'm glad I did.
DB: Yeah, it's interesting because one of the most successful on a content basis we've developed is an article we wrote on why we killed the connector. The connector is dead between application integration and direct API to API integration, by passing connectors is the future. And it incited a similar sort of response because it was almost an opinion piece, right? And people said, "Well, connectors work well for me." And you know, "I've been using them for years and they add value" and blah, blah, blah.
And so it was really valuable because there were valid points, valid discussion, and got the community discussing the whole concept and value of connectors and where the industry might be leading and it brought out a discussion. But whereas if it's a piece on defining an issue or describing a process, you know, it's interesting and it's useful if you're doing some work in that particular space, but it doesn't necessarily get the sort of traction that you want in content marketing these days. So let's move on to architecture itself. You've written a lot about microservices. Let's go into that space. Do you consider them to be evolutionary or revolutionary?
MR: Oh, wow. Do I consider microservices to be evolutionary or revolutionary? I would have to say, David, both. I think that microservices exhibit both of those. And let me explain why I'm saying both. I think microservices was evolutionary. In other words, defining that difference as, did we evolve into kind of this architectural style about six to seven years ago? And I do believe that we did, and that's what I love so much about microservices. I do believe that it was evolutionary. It was eventually going to happen. And let me explain why two things in my opinion, at least in my opinion, two things were really the catalyst for microservices. The first was this whole idea of continuous deployment. We had continuous integration and that was a good first step, but continuous deployment, when Dave Farley and Jez Humble came out with that book, was just remarkable.
I mean, this, this finally gave us the answers on how to effectively deploy software. And what if we all have a bunch of large monolithic applications that didn't work? So, it was this experiment, this evolution to say, "Well, what if we broke up the applications a little bit?" That worked. It was like, "Hey, what if we broke them apart even further?" That worked as well. And as we started to really break apart our applications further, we found the ability to do these effective deployment pipelines, continuous deployment, and continuous delivery. That was really the first catalyst from the evolutionary standpoint, in my opinion. The second one I observed was really Eric Evans with his revolutionary domain-driven design. I think this, these concepts really formed microservices. I'm bold enough to say, again, I love these bold statements that microservices would not exist without the bounded context to this concept that Eric Evans really drove through a domain-driven design.
And so I really tend to see David, these two as parents of microservices in a way, and that was the evolutionary aspect. But microservices - and I have been doing microservices for a little over six years now, almost devoting my whole career to it at this point for the past six years - I have also seen the revolutionary aspects of microservices. Microservices has finally beat us over. We've been beaten over the head about having to pay attention to data. Yeah, yeah, yeah. Microservices was the very first architecture style that came out that required us to consider data as part of the architectural design. No other architecture style in existence has required this.
Is it a good idea? Oh yeah. That's how you get an effective system, but is it required? No, we can still have this impedance mismatch, these two camps of architects and data architects, and they somehow combine the poor developers, try to glue them together. Well, microservices was revolutionary in this aspect. So that was really the first aspect. It woke us up to say, "Hey, data matters in architecture." Try to build a bounded context without data and you can't. The other aspect - revolutionary - that I kind of saw that was kind of the main one was really this data piece, but also the other revolutionary aspect of microservices was this real bridging of collaboration. Finally, finally, David, we've been trying to collaborate, not communicate between each other, but really collaborate working together on a cohesive system and develop that cohesive system. And microservices requires this collaboration. Without it, things completely fall apart.
And that's where I really get excited. We as architects have to collaborate with developers or it won't work. We as architects have to collaborate with data architects and DBAs, or it won't work. We have to collaborate with operations. Now we never really had to before, you know, we talked to them, communicated, but not collaborated. And that really was a second aspect of this revolutionary aspect of both the understanding of the intimacy of data and how it connects to architecture and really this core piece about collaboration and really building that. DevOps was a neat idea. I started experimenting with DevOps way back when I was an employee with IBM, and this goes back into, oh gosh, the late nineties, early two thousands. It was just a word. It was a thought. We experimented with it, but microservice requires it. And so it was really a catalyst for these things, revolution.
DB: If it's a revolution it's going to cause a lot of disruption. So what are the major hurdles for a company? What are the challenges that they're facing when they're implementing microservices?
MR: Wow. David, what a great analogy, because you're right in any revolution there is a lot of pain. There's a lot of collateral damage in any revolution. There's a lot of upset. Oh boy. And after six years so far and counting of using microservices, I don't think there's enough time in the week to actually go through all of the challenges and hurdles of microservices. But to your point though, there are some real key ones, David that I can really point out are things that are cautionary tales for anybody listening to this podcast. Thinking about microservices or doing it will either be nodding their head or saying, "Oh, I didn't think of that." Or even considering microservices going, "Hold on a little bit." And really that first one is, the first hurdle that I usually see is all about service granularity.
How big should a service be? And this is really, really hard stuff. Sure, our payment service, that we accept five different payment types for our processing - should that be one service or five? Should notification to our customers, which we do through SMS texting, email and even postal letters - should that be one service or three? And these are the challenges that cause teams to just, well, have, let's call it heated debates or, well, I was trying to think of a friendlier way of saying heated debate. Lively conversations, let's put it that way, David.
Service granularity is hard. The other is really a breaking apart of data. This is perhaps aside from service granularity, probably the biggest challenge, at least in my experience at clients' sites that I've been at and helping, it's really dealing with data and breaking apart data. Decomposing data is extremely difficult. Data is interrelated. We've got foreign keys. We've got relationships between data. When we start forming bounded context, it sounds easy and it looks good on paper.
So, you actually try to do it. And I was like, "Wait a minute, I need that data now, but you're saying I can't go query that table?" "Nope. You cannot query that table." "Well then how do I get my data?" That really is the second piece. The other - it's interesting, especially when we talk about serverless, as part of microservices - is what I'll call, well, deployment hell. We used to have DLL hell back in the C days.
And then of course we had JAR hell when Java came out. Well, now we have, in microservices, deployment hell, all these services dependent on one another and hundreds of them. And yes, we have operational automation to help us with this, but boy, we knocked one service out and all of a sudden things start breaking that we didn't even know were tied to it through workflows. And so, yeah, the deployments, although it rates really high in microservices, if not done correctly can be your worst nightmare. Dante's ninth level of hell is basically microservices done wrong and then, oh boy, like I said, I can go on with, you know, managing workflows. This is something that's a huge struggle in microservices. Service dependencies is where microservices really starts to fall apart. And these are some of the real major hurdles and challenges. Fortunately there are solutions to all of these.
DB: Yeah. Well, I mean you know, managed services for deployment and stuff like that is making it easier. And record or remediation by those public services, managed services, making that process easier, you know, if you were the public cloud provider. But this, this interesting aspect of the interrelationship of data and the bounded context, it's easier said than done, right? So whether you're designing a new app or breaking down a monolithic app, like you said, there's lots of relationships. And sometimes, you know, when we've been building microservices ourselves, it's like, you know, I don't want to call that data remotely. There’s going to be performance issues, there’s going to be data integrity issues, there's going to be all this other stuff. And so let's bundle it into the service, you know, and okay, well, we’re starting to build a monolithic app again and now they always recommend the concept of a microservice itself. It's a real challenge. Is there an easy answer to it?
MR: No. This is the problem, David, and your observation is absolutely correct. I can't tell you and won't tell you the definitely the clients and the number of clients that I have been in over the past six years that effectively have created a large, distributed, big ball of mud or what some of my clients call, "We have a distributed monolith," and I will step back and say, "Wait a minute, let me guess. You're using microservices." They’re like, "How'd you know?" and so, you know, it's so funny you say that, David, because all these new buzzwords are coming out, I mean, a distributed monolith is an oxymoron, but it really does describe the trouble you can get into with microservices. There are solutions to these hurdles and problems. A lot of those David are how I ended up learning these, which was battle-tested.
It was being in the trenches and saying, "Whoops that was not the right move." It was all those lessons learned and doing things the wrong way and saying, "Yikes that was not good, was it?" "No, let's do it this way now." And I really started recording all those things down, which is where I developed all of these antipatterns and pitfalls that I evangelize and kind of being in conferences and trainings and stuff it allows me the opportunity to be able to share all of those lessons learned about every single one of those hurdles I mentioned and techniques for overcoming those.
DB: Can you share some of the weaknesses you've discovered in microservices?
MR: Yeah. Oh boy. Weaknesses. Well, actually, we've touched on some of them just in the hurdles itself. But you know, there's two that are really coming to mind, in my opinion at the very forefront of those. The first is performance, and you might be surprised by that answer. But it, in fact, has been my experience repeatedly that most microservices implementations will in fact have less performance or worse performance, than your original monolithic application, or if you were to, from a greenfield, go to a monolith.
DB: Not many people would expect that outcome.
MR: You're right, David, and this is one of those "gotchas" that you end up with when you start not with maybe three or four services, but once you really start in earnest developing dozens to hundreds, to even thousands of services. There's three reasons why and this is not just an opinion. This is an observation that I have seen in the field for the past six years. There's three reasons. One is network latency. We tend to forget that when we're invoking another service, that's necessarily a remote service and we are going through the network and there is network latency that we didn't have before. Number two is security latency because if I take my monolithic application and blow it up, or even start out at a greenfield and we've got 70, 80, 200 services, well, when I start calling other services, I necessarily, hopefully, need to secure those endpoints because a service is a singly deployed or a separately deployed function, a single purpose function in microservices. It's separately deployed. Who can access that? Who can access the wallet service containing all of your PCI information?
And so consequently, when I start hopping around services to fulfill a request, not only do I have network latency, but also now I may have to reauthorize you for every one of those hops. At least I have to verify the security token I'm passing into the header. And interestingly enough, there is a third reason that's hidden away in the bowels of microservices and that is data latency. And that’s data latency. Let's say I want to retrieve all customer information. Well, in the monolith that was an SQL Join across seven tables. Yeah. This is what we did. That was pretty fast, about seven to eight milliseconds. Now I need to join and query graph seven different microservices, but each one has its own data and its own query. So I have now taken something that was very effective in the database in SQL Join.
And now I have to make seven database calls. Now, hopefully I can do this in parallel, which helps mitigate some of the data latency. But a lot of times I can't, I have to do a workflow. Which means that all three of those point to the fact that I may be adding anywhere from 500 to 1500 milliseconds onto every request. So that's why performance, again, it sounds surprising doesn't it? It’s like, "Wait a minute, no. Making things smaller should be faster." And it's like, well, if you're calling a single service from a single UI, great, how many applications do that? Not many. Not many, but you know, the other weakness of microservices is cost and complexity, the two big Cs. They're expensive. I make the joke, David, by the way that I usually say, "Oh, so you're using microservices. I can infer a couple of things about your environment." "Oh yeah. What's that?" "Well, you have a lot of cost overruns and high attrition." It's like, "How did you know?"
DB: Alright I don’t want to scare people away from microservices. Like you said, you know, it is a revolution and people are doing it for a reason. So what are some of the reasons? Where are they a good fit? Where does it work?
MR: So, there's so many, many good reasons why this is on the hype curve. Super high levels of scalability. Agility. One of the things that is near and dear to my heart is architectural change. Architecting for a change. I've been touting this in conferences, in various talks, oh my gosh, David, for almost 10 or 12 years about Agile architecture. And this was before microservices even existed.
And it was hard. It was hard talking about how to make architecture Agile, because architecture does change. Microservices has given us this. Five stars for Agility, Agility being defined as the ability to respond quickly to change. Let's face it. Why is microservices so incredibly popular? It's because businesses have to change on a dime. It's the only way some businesses can remain competitive. They have to change fast. Businesses are learning how to change business processes quickly, but then it hits IT and everything stalls out for months, years, crickets chirping. And so, that's one of the first things microservices has really given us is that Agility, that ability to respond quickly to change daily deployments. David, this is awesome stuff. I can make a change and have it in production in a particular microservice, a single purpose function within an hour and prod from problem, bug fixes, new features faster than our competition.
That's where microservices shines. Levels of fault tolerance done right is fantastic. Users suddenly say, "Wow, these systems just don't fail, do they?" Like, "Oh yeah, they're failing all the time, but you just don't notice it." It’s scalability at a function level. When we talk about evolutionary architecture, the ability to evolve the architecture as our companies evolve, this has the highest rating out of any architecture style for the evolutionary aspects of architecture. If I need to start evolving the architecture to add more functionality, do different things that our company's doing, taking a different direction. David, this is a matter of dropping in new microservices or adopting existing ones that are needed. Man, try to turn a monolith. That's like a huge 800 foot destroyer. It's gonna take four miles to turn that ship around now. We're not talking a little tiny speed boat. And so those are some of the main ones.
DB: Got it. I mean, there are so many compelling reasons, right? Like you said, the Agility that continuous deployment and Agility that is offering organizations, you almost have no choice. It's interesting to see how that's being driven down from large enterprise to smaller enterprise, because there is some complexity associated with microservices and, and so, smaller enterprises perhaps are not as well equipped to deploy it, but it's getting pervasive. It's interesting to see. I'd be interested to know your perspective of where it's all going and how potentially functions as a service fit into this because, you know, functions as a service and not really the bounded context is perhaps not well-defined. And I'm wondering if that's going to cause a mess in the future. What's your take on where microservice is going, how the functions of the service fit into all this? What's next?
MR: This, I get excited about this. I haven't been excited yet, but this, I get excited about. So where's it going? Basically in a nutshell, and then I'll kind of expand on this, but in a nutshell companies jumped on the bandwagon of microservices and company A's doing it, so we should be doing it. "I'll do all of our stuff in microservices or serverless." And the excitement about where it's going is understanding where we bend and what I am seeing in the industry as a whole. And these are companies that I work with, companies I'm in trainings or conferences that I do. What I'm seeing is a level of maturity starting to rise in microservices, not only about the hurdles that we discussed in this podcast, but also when to use it, when not to use it to really have, I guess I would say David, kind of a respect for microservices. Understanding it is complex and it's not a silver bullet and maybe we shouldn't use it.
And this gets me excited because I see that learning happening as teams and companies are getting and gaining these lessons learned. So where I see microservices really going is finally starting to reach that maturity curve where, yeah, it's been a great experiment and some companies still are in the middle of that experiment, unfortunately, but we're learning a lot and we're learning in my opinion, to be cautious. We're learning instead of jumping on that bandwagon and immediately embracing microservices, whether it be personal experience or whether it be the experiences of others like myself, that evangelize some of the lessons learned. It's taking a step back and taking a more cautious approach to saying, "Should we be using microservices?" The other place David, that I really see microservices going is more towards hybrid architectures. I think the other thing that we have learned over the course of, I'll say six years or seven years, is quite frankly, not every portion of an application has to be microservices.
We can form hybrids. We can have portions of our applications, embracing the microservices, architecture and portions being mini monoliths, or even service-based architecture. And this awareness, I am starting to see at my clients' sites and this excites me because it's like, "Oh I see half my work's already been done here," because you hardly are seeing some of the stuff that always about to evangelize for you. So, I guess I would summarize it in the sense of seeing it be a cautious approach with an understanding of hybrid architectures especially when it comes to that data piece, David. This is the part where not all data can be broken apart. And that means necessarily a lot of times we don't do microservices, but rather a service-based architecture approach.
DB: You've seen this out of people's own experience. You're talking about the battle scars. People are actually, as you say, maturing and realizing that they can have this hybrid approach and there are different approaches to the deployment models.
MR: Yeah, exactly. And also David, the tools definitely are maturing. Again, what I usually do with this step is also evangelize and give everybody who's listening the words of advice. The tools are making microservices and frameworks a lot easier, a lot easier to manage, a lot easier to deploy and also to even create, but the devil's in the details. And there's a lot of hidden aspects that are abstracted from us now in a lot of the frameworks and tools and the cautionary tale is really understanding embracing those but understanding those abstractions. When we talk about the ease of auto-scaling elasticity, which used to take me four months to architect is a switch that I set in Kubernetes now. I mean, how easy is that? Well, if I'm using an in-memory data cache, for example, or an in-memory data grid through replicated caching, and I've got a 500 KB cache and I all of a sudden spin up 40 instances guess what happens? I run out of memory very quickly. So, that's what I mean about the devil in the details. I appreciate the tooling and applaud the frameworks and the tooling that's happening with microservices to actually have it be feasible for most companies. But it still requires that level of maturity to understand the knobs and dials and what's impacted by auto-scaling for example.
DB: Yup. You mentioned that you enjoy the conferences. I'm guessing you're not doing a lot of conferences these days. So how can people stay in touch with you and hear your voice and keep up today with what your thoughts are?
MR: Well, the single place where everybody can go, the nice thing is my website Developertoarchitect.com and that's T-O so the movement from, think of, "I'm a developer. I want to be an architect." Developer to architect. And this is a website full of resources. Every other Monday, David, I do something called "Software Architecture Monday," which is a free video for 10 minutes. I usually keep the videos at 10 minutes of some aspect of software architecture. And these are free. You don't even need to sign up, you just watch them. And actually last weekend, I just published less than 105. So there's 105, 10 minute videos out there about some aspect of architecture.
The other thing is the upcoming events page on my menu item. There you can see upcoming events. These are the places where I'm actually doing, still, public training and some public conferences, still. I'll tell you though, David, I do really, really, really miss the in-person experience. It's hitting me hard. It started hitting me hard, late October, and it's hitting me hard now. I miss the interactions. I miss the feedback. I miss seeing people's expressions and collaborating on this stuff.
DB: I get it. I mean, I don't miss the travel. I’m happy to be not getting on a plane every second week, but yeah. There's nothing like that face-to-face contact is there. Mark, it's been a pleasure to have you on the podcast. Thank you very much, so many insights there. It's been a pleasure. Thank you again.
MR: All right. And thank you so much, David. And also Kevin, for having me on Coding Over Cocktails, really psyched about this. It's been so much fun talking with you about these ideas. This is important stuff to get out to everybody. I applaud you for doing this. Thank you so much for having me.
DB: Absolutely our pleasure.