This pattern is crazy, or I'm an idiot - Learning Domain-Driven Design by Vlad Khononov
Part 2
Book Covered

Learning Domain-Driven Design: Aligning Software Architecture and Business Strategy
by Vlad Khononov
Get the book →Book links are affiliate links. We earn from qualifying purchases.
Author
Hosts
Transcript
This transcript was auto-generated by our recording software and may contain errors.
Carter Morgan (00:05)
That means that you can get done in two days what you previously took a year to do. And like once you start putting in like concrete terms, like that's insane. That's laughable, right?
Hey there, this is Book Overflow, this podcast for software engineers by software engineers, where every week we read one of the best technical books in the world, an effort to improve our craft. I am Carter Morgan and I'm joined here as always by my co host, Nathan Toops. How are you doing, Nathan?
Nathan Toups (00:34)
Doing great. Hey everybody.
Carter Morgan (00:36)
Well, as always, make sure to like, comment, subscribe, share the podcast with your friends and coworkers, join the Discord. Anything you can to help the podcast grow. and some professional news for me. Nothing crazy, but I was promoted this week at work, which is exciting stuff. Yeah. Yeah, yeah. Official to principal engineer. So that's exciting. Thank you. Thank you. It's it's a good team. I like the team I'm on.
Nathan Toups (00:52)
That's awesome. Did is it a t title bump or what what you got?
Nice. Congratulations.
Carter Morgan (01:06)
and yeah, if you if you connect with me on LinkedIn, you can know all of my professional updates. I I will say to anyone trying to connect with me on LinkedIn, please just put like I listen to the podcast in the connect note. Cause like half the requests that come in have that, and then half are just random people. And I can't accept you if you're just a random person. But if you just say I listen to the podcast, I will accept your connection.
Nathan Toups (01:29)
I
I'll I have a I have a habit of accept accepting almost anybody in which a decent number are crypto scammers, which then I just have fun with. and report them and investigate what they're up to. It's been it's actually been a lot of fun. It's like a little hobby of mine, to see if we can play a cat and mouse game of like what Vercell website and GitHub org they're using and filling out reports. It's been fun. So if you're a crypto scammer out there, come and reach out to me on LinkedIn.
Carter Morgan (01:36)
Yeah.
I
Okay, this is a problem because the other heuristic I use for dis accepting connections is if they're a mutual connection with you. Cause I figure if they're trying to connect with both of us, then they'll probably come from the podcast. But this could be Nathan just accepts anyone.
Nathan Toups (02:08)
Yeah, do not do not trust my connections on LinkedIn because I yeah. I have a I have like a
hate-hate relationship with LinkedIn, but that's for another that's another conversation.
Carter Morgan (02:18)
Ha ha ha.
I had a recruiter reach out to me on LinkedIn, this was years ago, during COVID when the market was super hot. And we were like chatting about a role, and I was like, Well, and I we're talking about money, and like what I need is like this much. And he starts like demeaning me. He's like, Ha ha, idiot thinks you can get that much.
When he only has this. Like it was really, really bizarre. I'm like, I already make more than what you're offering. And he's like, It's like you could only get this. That's all you're worth. And then like it was weird. I wound up I I was a punk about it and like found like the VP of his recruiting firm and sent the screenshots. I was like, this guy's insane.
Nathan Toups (02:58)
yeah. I yeah, that's
that's wild. No, it's right. We're in a mad world and I do think that recruiters are in this like impossible job where it's like a a lot like real estate agents where there's a few amazing ones and then there's like most of them which are terrible and should not be in that job. and I feel like it's the same with recruiters. Like I've met recruiters that are just top notch amazing, everyone wins. And then there's a bunch who like I think want recruiter like the the recruiter bonuses that they get if they're good.
Carter Morgan (03:16)
Yeah.
Right, right.
Nathan Toups (03:28)
And just
have no business being in the business. So
Carter Morgan (03:31)
Yeah, I'm I'm generally positive on recruiters. I'm like, I'm not gonna be mad at someone trying to give me a job, but yeah, y you'll find people I think you're like that who like you'd be better off like selling instead of recruiting. And even then you might not be a good salesman, but at least it's a little more adversarial.
Nathan Toups (03:42)
Right. I yeah, I think I think a really
good salesperson could would I think that's a transferable skill. I think if you yeah. Anyway, I'm I'm not either of those. And so but yeah, I've I've had good experiences, I've had bad experiences and yeah, salty salty people are something something to deal with.
Carter Morgan (03:49)
Yeah, yeah.
My wife and I talk about that just because like, you know, with AI, I'm like, maybe I'll take our job. I told her I'm like, there's only two real jobs. There's there's building things and selling things. Like right now I'm building things and if building things is no longer a job, I'll just start selling things. Like so, but I as we've discussed at length on this podcast, I don't think we're in any danger.
Nathan Toups (04:16)
Right. This
You worst case scenario, I think I might just buy a TIG welder and learn how to, you know, weld aluminum or something, you know? That would honest day work. Honest day's work.
Carter Morgan (04:26)
There you go. There we go. Yeah. Definitely I'd like to see an LLM do that. All
right. Well, let's talk about the book this week. back at it again with learning domain-driven design by Vlad Kononov. Vlad is a software engineer with over 20 years of industry experience, during which he has worked for companies large and small in roles, ranging from webmaster to chief architect.
Vlad maintains an active media career as a public speaker, blogger, and author. He travels the world consulting and talking about domain-driven design, microservices, and software architecture in general. Vlad helps companies make sense of their business domains, untangle legacy systems, and tackle complex architectural challenges. He lives in northern Israel with his wife and an almost unreasonable number of cats. book introduction. We've got building software is harder than ever. As a developer, you not only have to chase ever-changing technological trends, but also need to understand the business domains behind the software.
This practical book provides you with a set of core patterns, principles, and practices for analyzing business domains, understanding business strategy, and most importantly, aligning software design with its business needs. So we read through chapter 11 this week. We're about two-thirds of the way through the book, and we'll finish out the book next week. But Nathan, what are your thoughts on what we've read so far?
Nathan Toups (05:38)
First of all, if we get Vlad on to do a an interview, I really need to know I need to quantify what an almost reasonable number of cats is. That that's like a must the the audience must find out. Like what is what is that number?
Carter Morgan (05:48)
Yes, yes. I don't know.
Yeah. That's was Dimitri Martin who had he had a joke about like like one is one one or two or three, that's a good number of cats, but like thirty-two, that's a crazy number of cats. But that is inverse with teeth. Where thirty-two is a good number of teeth. One or two or three, that's crazy. Anyhow. okay, so
Nathan Toups (05:57)
we're
no. Yeah. I think that I
I I mean I and I we have a cat, so I'm I'm like I'm a fan of cats, but more than two seems crazy to me. I can't imagine. I can't imagine like two cats, that's like a full house of cats to me. If you have three or more, I think that that would be an unreasonable number of cats. So yeah.
Carter Morgan (06:38)
Yeah, I I we have zero pets, so I don't
know. I have too many kids, that's what I have.
Nathan Toups (06:43)
I I think
that we'll have zero pets one day. I think this is gonna be the last cat for a while. great cat. We love her, but it does make traveling and things like that more complicated.
Carter Morgan (06:52)
Yeah,
yeah, that's been my hang up with it for a while. Well anyhow, as far as Vlad and his cats go. Wait if we discuss Vlad and his cats. Let's discuss Vlad and
Nathan Toups (06:59)
But how about my yeah,
all my all my thoughts on this book though. I I like that so we're we're getting into the nuts and bolts of things like this is sort of the we're we're transitioning from from one part of the book to the other. And so we're s we're start off sort of in this sort of tactical D D design stuff, and then we're and then we get into the last two chapters we cover are in the applying phase of like how do we apply these patterns that we've been talking about so far?
Carter Morgan (07:04)
Yeah yeah.
Nathan Toups (07:29)
The applying part's been so much fun. I I I I think we'll probably spend a decent amount of our time on this episode on chapters ten and eleven. at least if you know, if I have my way, but that's where we'll spend time. But it's kind of funny I was thinking about this because we we just we you know not that long ago read software architecture of the hard parts, which came out in twenty twenty one. And this book also came out in twenty twenty one, and you can see some overlaps in thinking.
Carter Morgan (07:40)
Ha ha
Mm-hmm.
Nathan Toups (07:58)
Right. Like there there's actually there's there there's really some now that I'm like thinking about these two books together, I it twenty twenty one, good year for software architecture, thinking about stuff.
Carter Morgan (07:59)
Right, right.
Yeah, it's I don't know. This book kind of had a similar thing where I feel like we read books like this in the past where the first third or so is spent just talking about like the principles. And I read those and I'm like, that well, that makes sense. This is great. Like I really agree with these principles. Then we get in some of the application, and some things just jump out of like this is crazy. Like I I never would have considered doing this, and
I don't know if this is any better. There's one pattern in particular I want to talk about kind of up top, which seemed nuts to me, but like maybe there's a really good reason for it. And I struggle with this sometimes where I'm like, is it just that the software I write is a lot simpler than than other businesses and what they need? Or is this just like kind of like a galaxy brained way of thinking about software? I don't know. so we'll talk about it and you, the listeners, can
chime in. yeah, I I guess like the the Galaxy Brain take to me was the event sourced domain model. And before we describe it, Nathan, did this seem like Galaxy Brain to you or were you just like, I've seen this before?
Nathan Toups (09:23)
So I will tell you, for the uninitiated, thinking about event sourcing w there's I think there's a time in your life as a software engineer before you saw event sourcing and after. And I'm not saying you have to choose to use event sourcing afterwards, but when you realize that, like you'll see this pattern, and then you're like, this is why Kafka exists. And you realize that there's like the whole, the whole like asynchronous,
Carter Morgan (09:46)
Right, right.
Nathan Toups (09:52)
Communication patterns where not only do we have pub sub, not only do we have cues, but we actually have this thing where we can go back and like any producer announces to an event sourcing log that these things are happening and then consumers get to decide where they are in the timeline and just process from that point and that everything's a pend only. It when you start having these large scale distributed systems where you really want to have everything decoupled, you really do have to have these patterns, like and we're and we're talking about
Carter Morgan (10:16)
Right.
Nathan Toups (10:21)
When you're trying to provision and plan for dozens of teams, right? Or dozens and or hundreds even sometimes of services, these these sort of have to happen, right? They you and you'll see the organizations that use these patterns. and you can kind of get like event source pilled a bit, because as soon as you start seeing this, you're like, man, if we had this, I wouldn't have to coordinate this team over here. Like I would just announce what my schema is.
Carter Morgan (10:41)
Right.
Nathan Toups (10:49)
have this thing that's up here. Now we just talk about producers and consumers, and I don't even have to coordinate anything at this point, right? Like it's it's a really I I like that he spent the time talking about this. And I think that also a book like Learning DDD is helpful, written in 2021, versus going back to the blue book, like the Evans book on DDD, which is sort of before all these ideas started to emerge. Like you you look at designing data intensive applications
Carter Morgan (11:10)
Right.
Nathan Toups (11:18)
A lot of these ideas starting to get introduced, but now that we're in the twenty twenties, these patterns aren't these like new and upcoming things. It's like the way that you do these types of systems.
Carter Morgan (11:25)
Yes.
Okay.
So so event sourcing for anyone who is unfamiliar is this idea that you don't store in your database like the final like current representation of the object. Right. So like for example, like let's do a ticket tracking system, right? So like
A ticket might get updated. You might update the customer's address. You might update their name. You might update the description. You might change the status from pending to assigned or whatever. And in like kind of the the simple way of thinking about it is like, okay, well, that's a a table in your database. And as you're making those changes, you're you're updating them. then we started talking about like event driven architecture, which I like. We use event driven architecture at work. And the idea there is that, like, you know.
As you're taking these actions, you're emitting these events, like, okay, status updated, address change, things like that. And I really like that from like a decoupled nature because you're gonna have the just these separate distributed consumers consume those events as they choose. But where I was like, man, maybe this is like Galaxy Brain take is he says, like, you shouldn't just have a table that's like, okay, this is the ticket, and this is the authoritative record of the ticket. Instead, what you should be doing is consuming all of those events and constructing in memory the
Right now, representation of the ticket based on all of those events, right? And so like you'll see, like, okay, like customer, you know, ticket started out as created and then move to a pending and then move to assigned and then move to complete, right? And so rather than just like reading from the database, like, okay, this was complete, you're gonna like stack all those changes on top of each other. And so like very quickly it'll assemble itself, you know, into the representation of the ticket. Like
Yeah, I I think that j that must just be the answer. It's just that like I'm at a startup and so we don't need to worry about this.
Nathan Toups (13:19)
So it
Yeah, it's so and a couple things because of the way that this works, we actually don't care how you're storing what they I think he you know, he uses the term like I think it's projection, is the term he uses. But th this is basically like I'm I'm I'm trying to do this without bringing up blockchain because blockchains are actually
you can think of it as an event sourcing model because you can read the entire ledger history to re- reconstruct the the current state of, you know, what everyone's wallet, like the values of of tokens that you have in it, you can go back to the beginning of the ledger, the vlog of the event log and replay the entire thing and all of us can agree that the ledger says the same thing, right? As long as the interpreter of those things are in the same. And so do I keep it in memory?
Carter Morgan (13:50)
Right, right.
Nathan Toups (14:14)
Or do I actually store it in a Postgres database? It's up to me. Like I, you know, if I have a ticketing service and a ticketing service consumes from the event stream, right, or event sourcing pattern. And then when you ask the ticketing service what this what the source of truth is, I should have a verifiable reconciliation between the two. Meaning this I should if I blew away the ticketing service and I could go back and play the event sourcing feed from day one, let's say, I should be able to reconstruct that exact state that's there.
It's it's it's completely reconstructible. most event sourcing patterns do have a lifetime. So, like you're not gonna keep all event source records back to antiquity. You maybe will keep seven days or 30 days, depending on what you need. and so you probably will have some point in time that you've kept like your epoch for whatever a reproducible window is, and then I can go back and replay for some period of time. And the reason we we I bring this up is let's say you find a bug in your code.
Or a bug in something that was omitted in erroneously in the event sourcing log, I don't go back and change that in the log. What I do is it, and these are called like temporal patterns. I actually put that record back in with the correction and I append it to the very end. And so when I reproduce it, I can go back through. It's kind of like if you have an you're in a company that does like really strict schema migrations, right? A good schema migration pattern is that I
Carter Morgan (15:24)
huh.
Right, right.
Nathan Toups (15:40)
All events, all changes to the events, I mean all changes to the schema should be in this reproducible order. I probably keep some state that says what's the what's the point up to where I've done schema migrations and it picks up where it left off, right? or if I start a brand new infrastructure, I literally will replay the entire schema migration history. very similar idea. And what's cool about this though is that let's say we have a new service that cares about ticketing.
events, activ ticketing activities, right? a ticket did this, a ticket did that, right? We're announcing these things on the event sourcing model. I can just start, I can make a new consumer and start replaying events from the earliest place that's available and start doing stuff without having to coordinate with anybody else. Right. Like and and again these should feel somewhat familiar. You're like, I can do some of that with PubSub. I can do some of that with Qs, right? But you kind of get you get both of these things and you get this like really nice
Carter Morgan (16:22)
Right, right.
Nathan Toups (16:38)
features where I don't have to worry about, but I drained the queue and that that you know that that that item in the queue's gone. It's not there anymore. I can't find it. and so it's it kind of it does. It changes your your thinking where we can move quickly as a very large organization. I have this like nice audit history of what's going on. and yeah I didn't I never thought about event sourcing
Carter Morgan (16:48)
Right, right.
Nathan Toups (17:05)
In the realm of DDD, but it's like a perfect fit, right? It's a perfect fit for all of these ideas of how we should break up and think about the structure of our application. Because once you can lean on the event store and projections as patterns, you end up having a lot more certainty in troubleshooting, for instance, right?
Carter Morgan (17:32)
Right.
Nathan Toups (17:33)
You have this really complicated microservices that are in place. Okay, but we still have an event sourcing pattern. I can go back and say, like tick by tick, who reacted to what? What's going on? Where are these things? I could I could even take a chunk of this. You can imagine a diagnostic environment. You could take a the whole event sourcing feed and feed it into an alternate implementation to reconstruct and see what what's the application doing under the under some deep scrutiny and stuff, right?
Carter Morgan (17:43)
Right, right.
Nathan Toups (18:03)
but yeah.
Carter Morgan (18:03)
Yeah.
And I really do like that about yeah, and maybe maybe I don't know. Maybe it just is the natural evolution because I like that about event driven architecture. We we anyone who knows who's follows podcast knows that we are in the middle of a big migration at work. You know, I'm not gonna say in the middle. We are near the end of a big migration at work. we are just we actually just finished today the we basically broke down
Nathan Toups (18:24)
Right.
Carter Morgan (18:32)
Every page on the website. And like we have to point them from the old GraphQL service to the new rest service. And so we've we've transitioned all the pages, which means all of the endpoints are created. There's like a few, there's like some webhook stuff and like a few kind of like scheduled jobs we're still writing. so we're we're we're near the end here. But anyhow, but part of what we did was an event-driven architecture because we had a lot of kind of like side effect stuff, like sending emails or updating.
records in the CRM or notifications, things like that. And so we went did that in an event-driven way. And so I've like we've run into places where like, we had a bug in the way we process these events. So that's fine. Let's just ship the new consumer. And then we'll just go back and and drive the events again. We use AWS Kinesis for our we we looked at it. It was like yeah. Yes.
Nathan Toups (19:22)
Which is Kinesis is great. I I've I've used
I used it for a large scale distributed web crawler, with Lambdas and a bunch of stuff, but Kinesis is awesome and it's it gives you a lot of what you would want from Kafka without having to become a Kafka expert, right?
Carter Morgan (19:39)
That
that's what we looked at. We were like, okay, like setting up like SQS is not enough. Right. Like we we need something a little more than like SQS. And we were looking at like having to spin up like new SQS queu every time we wanted like a new, you know, consumer stream. We're like, well, we don't like that. And then we so we're like, okay, well, Kafka is the other option. We're like, that seems overkill for what we're trying to do right now. So Kinesis was like a good middle ground option between the two. We'll see how that treats us in a year or two.
Anyhow, so I like event driven stuff. It's been working out really well for us. And yeah, maybe this like event sourced you know, I mean what is he what I just the event source domain model. Maybe that is like just the natural extension of event driven architecture. Like it's not crazy.
Nathan Toups (20:25)
And you may get there.
I also love that he brought up something that's I think is also true. Sometimes we'll overload the term advanced sourcing, where what folks really mean is c is CQRS, which is the command query responsibility segregation. Are you familiar with this term?
Carter Morgan (20:41)
No, well he talked about it, but I didn't grok it entirely.
Nathan Toups (20:43)
Mm-hmm. So it's it's kind of what
you guys are doing already, right? Which is this idea of this clear separation between something that writes and something that reads from this event stream, right? and so there's this idea that I write to it with maybe some contract of how I should have the shape of the data, but that the reader is actually the interpreter of those events. And those are sort of decoupled. And the reason is because my reader may evolve over time.
Carter Morgan (20:53)
Right. Okay.
Okay.
Nathan Toups (21:10)
Right. And he the cool the kind of cool thing he talks about here is that like you get these sort of you get these sort of like these evolutionary patterns start to emerge because the business changes or you realize that there's competitive advantage to bringing something in house. And so with CQRS is it's really important that like you have a right model, you know, it you can think of a lot like how an API is is created and you know how how you might want to take care of like not making breaking changes to it and things like this.
and then the read model is just any reader can is kind of up to the interpretation itself, right? And this is what gives you that decoupling is sure. Maybe you have a standard and you say, hey, here's the schema we have, and everyone should try to approach reading it like this. But if a team wants to come up with some radically new idea or only cares about a certain type of event that's being written, it's really up to you, right? And I that pattern is really powerful.
even if you're not doing strict event sourcing. and I think that that that's sort of the and and I will say he does a really good job of giving trade offs. I think
Carter Morgan (22:11)
Right.
Yes, yes, he
he he really did. He wasn't like, This is the one true way of building soft.
Nathan Toups (22:22)
'Cause I I was kind of like holding my breath a little bit 'cause like I I do actually love some of the art the patterns that he gets into because he talks about layered architecture, ports and adapters, which again people who love or hate D D I think a ports and adapters are one of those that I I hear about a a lot or the the what they call like the hi hexagonal hexagonal architecture, CQRS. and then he talks about how like these are there's trade-offs to each one of them.
Carter Morgan (22:41)
Yeah.
Nathan Toups (22:50)
Right. And maybe your business models itself best with a later layered architecture. Maybe ports and adapters is a better fit. Or maybe you want to have the CQRS for these things. And I thought that this I think it was chapter eight that really got into this. It was it was enjoyable. I I this was a kind of thing where I'm like, I would go back and reference this again, if I was kind of tingled up somewhere.
Carter Morgan (23:12)
Right, right. Well,
and and that to me is just one of the value of like being well read or listening to this podcast is like just understand like you just get exposed to these ideas, right? And like, you know, we're doing event driven architecture, but like i I, you know, say what you will about like event source domain model, right? Like I don't think it's a very intuitive pattern at all, which is not to say that it's wrong, right? Like a lot of the best parts of software are not necessarily intuitive.
and so again, I don't know if I'll ever pick this up in my life. I don't know if I will ever, as you know, a lead decide like this is the pattern we're going to use. But if I join a company that's using this pattern, right, like at least I'll, you know, it won't seem crazy to me. And, you know, who knows? Maybe we will get to a point where I'm like, where we're finding like Jesus Lee is like we're as we've grown, we're all having a really hard time agreeing on like what the definitive state of the
The model is in our system, what do we do? And like, well, that's where the event source domain model comes in. Like just admit the events and let people reassemble them themselves and they can, you know, act on the event at any point in time, which like is kind of like that's neat conceptually. It's like time travel.
Nathan Toups (24:31)
It is. in this data warehouse project that I'm working on, this data lake really is what it is, is we're really pedantic about a temporal model and data lineage, mainly because we're making business decisions on this data and we need and we're even building, you know, AI models and things on top of it. And I need reproducibility. I need to say, like a lot of times we'll get new data in that's corrections to like public data that comes in or even private data that we purchase.
Carter Morgan (24:52)
Right.
Nathan Toups (24:59)
And I need to be able to go back in time and say, why did we make a business decision? actually, it's because this public data source had not been corrected on this quarterly basis. And we would want reproducibility where I I should be able to run the model as of what I thought the truth was at some point in time. And you have to build it in a very deliberate way to do that. And I maybe you're right. Maybe this the when you kind of have these awakenings of like, what does that actually mean to do this? You do kind of feel a little bit of galaxy brain.
Carter Morgan (25:05)
Right.
Nathan Toups (25:29)
stuff because you're like, I can rewind time. Like I have I have access to because but you know, but a lot of times you you're mutating state. And we we see this even just in regular programming, why we like functional patterns over imperative patterns, right? Is that I need when I start reasoning about complex systems, reproducibility becomes really important. And so in a functional pattern, if my constraint is that all inputs wire into outputs and I can think through the chain.
Carter Morgan (25:33)
Yeah.
Nathan Toups (25:58)
And there's not magical state transitions happening and secret external function calls. I can compose really complex things. And I the same thing applies to these distributed systems. It's like if we can agree on this pattern of reproducibility, even if I have no control over all the events that are being in there, I can audit the event stream. I can audit what's going on and and digging in. And so yeah.
No, it's super, super cool. And I guess this kind of naturally transitions into the the next chapter, which is the communication patterns.
Carter Morgan (26:31)
Yes, yes. We
we he he covered a pattern actually posted it on my work Slack because we use this at work. the outbox pattern for event driven architecture, which is this idea that and you know, this is actually one I discovered this via I I think I was using ChatGPT at the time. because I was really concerned with this idea of like, okay, so let's say, like, you know, using Leland as an example, right? Like,
I book a session with like one of our experts, right? And but then I need to send an email for that session. I need I I need to send the email reminder to to the the coach or maybe a text reminder or or anything like that. Right. Like that has to happen. and that's gonna we know that's gonna happen in like an event driven way. So like
What do we do? And then like this isn't a great example because it's notification. But there are some events where basically you say, like, this event, this action is not complete unless the associated downstream effects from the event also happened. So I'm like, okay, so so what do we do there? Or like, or you can have the other scenario where it's like, okay, well, what if the what if persisting this to the database fails, but then we accidentally emit the event too? And that's what they recommend is the the outbox pattern, which is this idea, like instead of just publishing the event.
Like straight to your event stream to your, you know, SQS or Kafka or Kinesis. Instead, what you do is you have a table in your database called the Outbox. And what you're writing to that is the shape of the event. And then you have some sort of like CDC process monitoring that table. E proposes two ways. You can do the push versus pull, right? Which is like you have the CDC process, which is monitoring that outbox table, or maybe you just have some sort of wrong, long running polling consumer, which is just consuming from the outbox.
and then as you can assume from that outbox, then you're publishing the events. And when I proposed this at work, people were like, why would we do that? Like this doesn't make sense. And the reason why you want to do that is because that way, you are when you're just right to the outbox, you can bundle it in the same transaction as the actual thing you cared about happening, right?
And so, you know, if you're trying to book in the database, but it's like, you know, you're trying to modify the database, but the data's corrupted, or it's an improper write or something like that, then it will reject both the database write and the and the outbox, you know, the the domain model update and the outbox update. And what that also gives you is you know, basically the reverse, right? Which is you can know, okay.
If this has been written to the database and is now kind of recorded as the truth, I can also have confidence that the event will be omitted, right? And that's another thing you get with the outbox pattern is like as you're pulling this outbox, you can mark the event rows in it as published, right? And so if you're having trouble emitting an event, it gives you some kind of like baked-in retry capabilities rather than your events being super ephemeral.
Which is very easy to do if you're building an event driven architecture.
Nathan Toups (29:57)
Right. Yeah, and and these are the the way that he digs into these examples and stuff, again, super valuable. really enjoyed this section of the book. He he also talks about sagas, which sagas are also talked about in software architecture the hard parts. you know, his focus is a bit more on processes like you know, using choreography versus coordination and these these other pitfalls that can come in. I think that software architecture
Carter Morgan (30:12)
Yeah, yeah.
Nathan Toups (30:27)
software architecture, the hard parts gets a little more in depth in these topics and so they they complement each other, but it's nice to see how sagas fit into a D D D sort of focused book as well.
Carter Morgan (30:38)
Right, right. I mean, there's some other stuff here about the idea of like you need a process manager, which is you know, as you are running the saga and you you have to decide like okay, like as events come in, like who handles what, right? And so there's gonna be some sort of like kind of state machinesque process, like that's a process manager.
There's a lot of different approaches on on how you can do that. some are and we talked about this with software architecture, the hard parts, right? Some are what do they call orchestration versus choreography, right? Like you might have one big central service managing where everything goes, that's orchestration, or you might let the events kind of be a little more self-routed and have a bunch of distributed consumers, and that's that's choreography.
Nathan Toups (31:30)
Exactly. And and
again, there's trade-offs because some of these are compatible with other things, like if you have a highly synchronous system versus asynchronous process, choreography versus orchestration, the all of these things you end up becoming your sagas can end up be a beautiful way of doing things in a correct path, or they can be I mean, again, self-architecture of the hard parts has one called the horror story saga, right? Which is sort of like worst of both worlds where you have this sort of distributed.
Carter Morgan (31:54)
Right.
Nathan Toups (31:59)
monolithic thing that actually can't guarantee correctness. And you can, you know, you can set this up really poorly. And so I think reading books like this are helpful because you know, in some cases, using a centralized coordinator is really nice. orchestrators are very common, especially in like things like DevOps, where we, you know, we do want to have a single state machine that understands this sort of state of stuff. But you get to a certain size and scale where eventual consistency is okay.
Carter Morgan (32:14)
Right.
Nathan Toups (32:28)
And you want to decentralize things and you want to have event driven architecture where it's eventually consistent across the entire system. But then what it unlocks for you is the fact that you can go horizontal to you know levels of compute that just not possible with an orchestrated coordinator. And but yeah, but there's trade offs. And I think again, books like this are excellent for understanding what am I getting myself into.
Carter Morgan (32:45)
Right, right.
Have you worked on a big like distributed system like that that's really event driven?
Nathan Toups (32:58)
No so I've never been I've
never been on teams large enough to do full on I I have support I I've been at a company that had some of this in place, but I was not on those teams. So I would kind of like be a fly on the wall. have you? Have you?
Carter Morgan (33:12)
I
No,
well, I mean, this is one of those things where like we did a bit of this at my last company, but we kind of had like a whole like data team that was playing a lot more in like the event-driven world. and I was a little more on kind of like the nuts and bolts crud side of things. so I I haven't had this. And then when I was at, you know, the big cloud provider, that's one of those things where it's like,
Nathan Toups (33:27)
Mm-hmm.
Carter Morgan (33:42)
You learn a lot if you kind of go like the Fang direction, but also so much of it is abstracted away from you, right? There's so much kind of like batteries included out of development there. And I kind of wish like, I don't know if I'll ever go back to like a big Fang-esque company. I don't think I'll ever move to Silicon Valley. And I don't who knows what remote opportunities look like, right?
but I kind of wish I could go back, especially now after we've read so much, because I think there's a lot, I think I'd be a lot more curious and I think I would learn a lot more about how things are done at that scale. Whereas I think when I joined, I was it was really good opportunity and I was very excited. But I think there was a little too much of me just like trying to keep my my head above water that you know, I I'm better equipped these days.
Nathan Toups (34:34)
Yeah.
Well and I will say the environments in which these things are implemented well are largely invisible. Like so especially if you're earlier in your career, you may not even realize how sophisticated, you know, your event sourcing work is because sane defaults are put into place, these things are just available. You may not even understand why your service is able to react to everything else. And the software architecture side of this becomes incredibly important.
Carter Morgan (34:43)
That's true. That's true.
Nathan Toups (35:06)
And again, we also have like a really there's a there's a big moving target. It's funny, like Kafka's been out for a while now, but I still feel like there's folks that are in in l being introduced to these patterns as they come up. And we're actually again, we're doing this as well where we're trying to understand the daily sort of transactional needs of the business with data that's coming in. And then we also have these like long-term lake house sort of
Carter Morgan (35:18)
Right. Right.
Nathan Toups (35:37)
analytics stores that we have. And we've realized that Kafka actually would serve us quite well, where instead of us having to have pipelines that kind of go into the lake house and go into the business and kind of have a dependency graph on each other, it'd be much nicer if we could ingest data from the outside world and r write these events that these things happened to a Kafka queue in which the in in which the
Analytics warehouse is like, cool. I have a bunch of data I can slurp up and we'll shove it into there. And then this event system also says, cool. There's like daily data that the business development team needs in their CRM. and both of those can just r have their own consumers responding to this thing. Yeah. And so that's what that's the direction we're going because we realize there's a bunch of stuff we're doing in these Kubernetes clusters. There's a bunch of things that we'd like to just have this idea that.
Carter Morgan (36:24)
That's nice. Yeah, yeah.
Nathan Toups (36:35)
Any system could talk to any other system if the they care about the consumption of events that are coming out of some other piece. And then all of a sudden we like the the interface becomes can you read from Kafka? Do you understand which feeds and and you know stuff that you're you're pulling from? And so that's we we actually were working on some design documents right now. And again, reading books like this is really fun because I'm like, yeah, I we need to think about the trade offs, we need to think about again.
We get into chapter ten, which is design heuristics. and I I I actually I ten and eleven like got me going. This was this was a lot of fun. specifically in like he talks about these decision trees of
Carter Morgan (37:07)
Right, right.
Ha
Nathan Toups (37:22)
Of doing like simple and complex thinking through, like, you know, I think one of the things he was talking about was like business logic patterns. Like, do I need to know does the history really matter? Right. If you're in a highly regulated industry, for instance, the history might s matter for regulatory reasons, right? You want to make sure that no one obfuscates decisions or something. You can imagine that.
Carter Morgan (37:36)
Right, right.
Nathan Toups (37:51)
Quite naturally CQRS or event sourcing becomes really important because I'm like, you know what? Auditors are gonna come in, they're gonna wanna know why we made these trades on the stock market or or a bank, and you know, account balances have to be like super locked down. You these patterns just sort of naturally emerge in these like highly regulated fields, or where you need correctness. but yeah, i i again, like I also
I I also love he you know just thinking about these domains that you're in. ports and adapters, right? We've talked about this in the past where naturally I'm a big fan of inversion of control. I'm a big fan of these and inversion of control isn't ports and adapters, but ports and adapters uses inversion of control if you really think about it, where
Carter Morgan (38:28)
Right, right.
Yeah, do you wanna explain the ports and adapters pattern for our listeners?
Nathan Toups (38:38)
Yeah, yeah, yeah.
Actually I'm gonna pull this up so I'm I'm not like doing something really goofy. and
Because a lot of times you'll hear people complain compare ports and adapters versus layered architecture. And layered architecture is one that I think people are you know, that's like the presentation layer, the application and domain, and then there's this data layer, right? Like that's sort of what we think of with a lot of like more traditional web apps and stuff, right? Like I have this UI layer and I have like the business logic, and then I have data underneath. ports and adapters is this idea.
that you have these like you have these areas of responsibility that you can I'm trying to I'm trying to see if I can find the the the image here. All so the business logic sort of sits in the middle. And then everything that it's like coupled to is try you try to extract abstract these away. So you know you basically have this ability to hot swap the data part, the swap hot swap telemetry, hot swap
these other components that are going to be in place. And it's all kind of like sitting around this like central, this central piece here. And I I'm trying to it's so funny because like I've I use this pattern in various ways, but I've never been like a DDD maximalist on this. But I'm like, anytime I read about the hexagonal architecture, I'm like, I kind of like I kind of like naturally drift into this anyway. I'm I'm just trying to find a good.
Carter Morgan (40:04)
Right, right.
Nathan Toups (40:18)
Yeah, so like the idea of like ports and adapters is that I have my application. Maybe in the adapters layer, I might have like a rest controller, right? This is how I get into my like external application. I have a message queue adapter, right? And and you again, if you if anybody who does a dependency injection or inversion of control, this seems really natural. It's like I I my business logic doesn't have any knowledge of the implementation of how I talk to the queuing service.
All it knows is that there's this hook to get into something that is a queuing service. It just so happens that my adapter goes to RabbitMQ, right? Or it just so happens that I have a a fake on my local dev machine that's like RabbitMQ enough so that my business logic functions, right? and then you get this like really they call it hexagonal, but there's actually only like four areas. It's kind of weird. The top and the bottom don't have anything on them, but you have like
Carter Morgan (40:47)
Right.
Right, right.
It's hexagonal
with four sides. I think we have a name for that. Yeah.
Nathan Toups (41:15)
Yes, it's he hexagonal with like two inactive sites, right?
but you know, so you you'll have these like communication adapters. So this might be like an email or SMS, like you'll see these kind things. you have a data storage adapter. but the idea is that the business logic stands on its own. It's just it's central to the way that the business functions. And then all sort of like external functionality gets abstracted away. So and again, like I I think that anyone who like
Carter Morgan (41:33)
Right, right.
Yes.
Nathan Toups (41:45)
If you've used dependency injection in a serious way, you do this naturally, right? This is this is this idea that maybe I have some bootstrap step or a knit step and I will have my log provider or I'll have my telemetry provider or have my database provider that kind of comes in and I've business logic has no idea that like what it's doing other than maybe I've given it the ability to you know initialize client.
And that client, it just happens to be the DB client and it it maybe has the ability to do some calls and do some stuff. But what db, it has no idea. Right. I'm not hard-coding, you know, maybe Aurora Postgres, you know, implementation details into my application. It's completely abstracted away. My adapter handles the idiot idiosyncrasies of whatever flavor of Postgres I'm using or what you know, maybe.
Carter Morgan (42:22)
Right, right.
Right, right.
Nathan Toups (42:41)
Maybe I'm using SQLite for local dev and then Postgres in production. My business application, I mean, the application doesn't know the difference. It just knows that my my little adapter that I'm using should, you know, be in a certain shape.
Carter Morgan (42:56)
Yeah, I really like
I really like this. I've actually been doing this. I've been working on like a personal project and have been like like I need to in production, it's a personal product, there's no real production, right? It the back and forth all happens over email, right? But locally, like I need to simulate have you know, doing emails. but I don't want to actually set up like some sort of real email system locally. And so
I created basically two different like email transport systems. One is like the actual one, and then the other one is it uses like local storage just in the browser to like simulate emails getting sent back and forth. Right. and I really, really like that pattern because like you I like keeping the decisions like just in one place. You just like, hey, if the environment is dev.
then use this, you know, interface. And if not, then use the real interface. this was where I was like earning my keep with Claude because like Claude initially when I said like, hey, I want to, you I I need like some sort of like local storage mechanism to simulate emails like, great. And inserted like seventeen if statements throughout the application that were all like, if, you know, we're in dev, do this and or else do that. and I I told him like, no, no, no, like we should do like like a a dependency inversion principle here and
And you know, almost like the strategy pattern. So I really like this. I think it's a good pattern.
Nathan Toups (44:34)
it's great. I so I did something I did something that I think was really helpful. So I've been I've been going to bespoke software in Claude, you know, just turns into craziness. But for bookoverflow.io, it's been sort of my little lab for tr trying out all kinds of stuff. And I now have a bunch of administrative tasks that live through a a command line tool called it's called Bactal, which is book overflow control.
and Bactol actually it this is a weird thing, and I didn't know how I felt about it at first and actually kind of love it now. All the services on our website are actually like service modules, and I can use those exactly so if we do things through the administrative port portal and panel, it uses the same exact libraries as I can use from my command line tool. So they're completely shared libraries where I've abstracted away.
Tasks, whether it happens through back end of a website, like I'm updating books through a graphical interface, or I'm batching a bunch of stuff with this command line tool, because I use like these little Toml configs and I can do a bunch of cool stuff like add an episode to the queue and push all the other episodes back and just like a bunch of administrative things. And I've built a skill around it. but part of this I also wanted to build an audit log because I'm like, if I'm gonna let Claude handle some administrative tasks, I really want an audit log to tell me.
Carter Morgan (45:56)
Right, right.
Nathan Toups (45:58)
Everything that's happened. Well, the cool thing is now we have an audit log on the website. So if I do any administrative tasks on the website, I get the same thing in the business logic's entirely the same. It doesn't care if it's running in command line tool context or it's running as a back-end service because the service modules themselves are web server agnostic, right? I can run it in the command line tool context or I can run it there. And so what I what do I have when it's a command line tool? well, I have a wrapper that has like flags and
arguments that get passed in, or maybe it parses a Toml file that has a bunch of structured data. But all of that's abstracted away in adapters. So the service itself, you know, it doesn't know anything about Toml. It just knows that some adapter took some Toml, puts it into structured data, the service itself handles it. And if it's a web interface, it's probably came from a web form, right? It's a web form that again turns the data into the shape that I expect it to be. That's an adapter, this like sort of like web form adapter piece. And
So yeah, this is like it ended up being in super productive. It makes it super easy to test, makes it super flexible. I have a single code base for my administrative tasks from the command line and the web graphical interface. And it's been a delight to to like extend. I've been able to add all kinds of little features with confidence because I have excellent test coverage. I understand like I can go back and read the code and go, this is this like these cool service modules that I have in place where the business logic is just like.
super clear and I've abstracted away all the different formalities around like how does it get in and out of the database? how does you know if I post operation from the web service versus using Toml from the command line. And I don't know, it's I I again I was I was kind of looking at this and gonna be like, this is it's because I have like really nice I have a nice like hexagonal architecture here.
Carter Morgan (47:53)
I love the ongoing evolution of the Book Overflow website. It's I one, the website is much better than it used to be when it was just a React template I bought. Two, it is completely overkill in terms of like
Nathan Toups (48:05)
yeah. I well, I j just so you know, I just introduced I just introduced
search ranking. So this is another ridiculous thing where it it I'm glad we have transcripts from the episodes, but you can full text search those on the website. So if you want to see every time Carter's mentioned Disney, you know, you can find it. And it tells you down to like the timestamp. Only a couple times. And or but but the the more the more important thing though is if we want to say I want to look up John Oesterhouse.
Carter Morgan (48:11)
Nice.
Yeah. Only a couple of times.
Nathan Toups (48:34)
Right. Before it would basically sort it by any mention of his last name from most recent episode back. And that's not actually probably what you want. You probably want the relevance score. So if I look up Osterhout, I probably want to see the episodes that he was in or the times of the episodes that we had books by him that were read. And so now if you type in Osterhout,
Carter Morgan (48:35)
Right.
Right.
Nathan Toups (48:59)
That's exactly what happens. So th there's a relevant score where if you're listed as an author as a guest, that gets listed higher than if you're just listed inside of like the the text of the this was just for me to be like, I don't know how to actually build this and like sat down and thought about it. And I was able to do it all with Postgres and some other kind of cool stuff. and yeah, I'm learning as we go. And it's like it's just been a really funny and fun thing of being like, you could we also have a public backlog now. And if you're a Discord member, you can vote on
Carter Morgan (49:13)
Right, right.
Nathan Toups (49:29)
books that you want to see next, which right now I think it's I think it's the t the Tanya what is that?
Carter Morgan (49:39)
Is are we doing a Tonya Riley next?
Nathan Toups (49:41)
No yeah. Tanya Riley, The Staff Engineer's Path. That's the most popular book on our public backlog.
Carter Morgan (49:47)
I've read that one before. Or wait.
Or did I read Staffinger by Will Larson? I can't remember which one I read. Yeah.
Nathan Toups (49:52)
We read Will Larson when
but we I I think we were we so the thing is that you can propose books in our Discord and now that this is the other thing that's ridiculous. You can propose books in our Discord and I've now made a Discord bot that can go through and scrape all of those proposed books and then I can decide whether we actually put them in the backlog or not. And we keep we keep track of the state of the ingest of like did I accept it, did I reject it? Did I defer it?
Carter Morgan (50:14)
Ha ha.
Nathan Toups (50:22)
It's so ridiculous. I'm I'm having a blast. So
Carter Morgan (50:25)
Please please
please understand that all backlog boats are purely advisory.
Nathan Toups (50:30)
They are they and they are and
and and Carter and I both get 20 votes each, by the way. And so early members I think get five votes. We get 20 votes each. And these are advisory. Like we just I what I wanted to see was is there public sentiment on books that we already had in our backlog, right? So Systems Bible by John Gall. We know we want to read that at some point. Well, it's it's number three on our on our backlog voting system. So we can look at this in
Carter Morgan (50:35)
There we go.
Right, right.
Nathan Toups (50:59)
you know, prioritize based on that. And we know that at least some subset of our audience will is gonna be excited to have us cover it.
Carter Morgan (51:07)
Something else that he talks about in chapter 10 is this idea of like talking about heuristics, right? Which is like, okay, how do you know? Like we're talking about bounded context, like subdomains in particular, right? Like, where does a subdomain begin? Where does it end? Right. And the answer to that a lot is it depends. And I think his buddy was like he he quoted a friend of his who basically said, like, there are lots of heuristics when
Trying to determine like what a subdomain is. He says size is one of the least useful heuristics. Like some subdomains just might be really big, some might be really small, right? I like this idea of heuristics. I I think judgment is has always been important in software engineering. But again, taking a page out of Fred Books's worldview, with Medical Man Month, like there's essential complexity and there's accidental complexity.
Nathan Toups (51:40)
I liked that.
I don't know.
Carter Morgan (52:03)
And essential complexity is where a lot more judgment is required. You know, we actually had it, it's interesting. We have now seen the same failure mode twice with our database during our big migration. Because we we switched from Mongo to Postgres. And so we had to write bunch of SQL queries where, and like we've been using Claude to do all of this, right? We've been we've been verifying, but like, you know, Claude's been writing a lot of code. Where Claude wrote two SQL queries that were so awful that if they got
Called in any sort of you know elevated capacity, it could take down the entire database. and it was really interesting. Like, because like some of the engineers on our team were like, well, humans can write bad SQL queries. Like, of course, humans can write bad SQL queries. But the two failure modes we saw with this, a human wouldn't have made because the first one was just like this insanely complicated query to like get all this information we needed to return it all in the in the right shape that we
Nathan Toups (52:39)
Right.
Carter Morgan (53:02)
Wanted. And at some point, a human would have stopped and been like, This is crazy. Like, what are we trying to do here? How is this monstrosity happening? Right. And because that query was so insane, it was just doing like these joins and all these different tables, like it was super, super inefficient. So I don't think a human would have written that. And then the second one, we actually looked at it when we saw that it was putting a lot of pressure on the database, and we're like, How is this putting a lot of pressure on the database? It's like a lookup to return customer profile information. Like, this is crazy.
Nathan Toups (53:08)
Mm-hmm.
Carter Morgan (53:31)
But what it was was at the end, it had this or basically said, like, look up this data for, you know, find up all this, find all this data if the ID matches the user ID or the customer ID. And because it had that OR at the very end, Postgres couldn't use the indexes on the table. And so it wound up performing sequential scans of both tables every time this was called, right? Which is like hundreds of thousands of rows. So
Nathan Toups (53:56)
Well.
Carter Morgan (54:01)
Yeah, it was just it was really interesting failure mode because on that in particular, user IDs and customer IDs are completely separate things in our system. Like we we never treat them as the same thing. Yet Claude reasoned that they might be and so added that there. And so we didn't catch it in review, which I think is another big problem with agentic development. Is like you're just you know, you don't review PR code as carefully as you write code, right? And and so it just snuck through.
But if he we never would have made that mistake. We never would have thought to put that or there because in our understanding of our domains, like we know that these are separate models, that they don't they have overlap, but like they they're never treated as the same thing. and so I I I thought that was a case where like Claude like doesn't really have judgment. We have an interview coming out, I don't know when, but with some authors we really, really like. and we talked about Claude.
Nathan Toups (54:40)
Right.
Carter Morgan (54:57)
and and large language models and they basically call them like advanced beginners. And they they really lack that kind of judgment. Yes. I I could talk all yeah.
Nathan Toups (55:01)
Yeah, I love that framing.
I was talking to another software engineer
at the gym this morning. I was like there and brought that up. Like we were actually talking about that in general.
Carter Morgan (55:14)
Yeah, yeah.
Yeah. anyhow, so I judgment has always been important in software engineering. It's even more important these days. Again, in a world where velocity is faster, like it the these tools are magnifiers, right? And I do think they make good developers a lot faster. Again, like I hear talk about like the hundred X developer. And and I like people just point out on Twitter, like, okay, a hundred X.
I do think large language models for certain tasks, like I actually think a lot of the work you're doing with the Book Overflow website, or like yesterday, because we've had trouble with some of these bad queries sneaking through, I wanted to I wrote us a a script to like run explains on every single query we have. And then I use that same script to
automatically run explains on every PR we do, just so that we're we're getting some insight and and nothing terrible sneaking across. Like, and I was able to move really quickly with that because this was like just kind of like tooling code. and I didn't really care so much about like what it looked like. And so that I'm I I think I'm willing to vouch and say that there was a 300% improvement in productivity. That the stuff I got done in about half a day probably would have taken
Two to three days in a pre LLM world.
Nathan Toups (56:45)
And and I think that that's the thing that I've noticed as well, which is that there are there are flow states that I'm in that I think I probably do a two to three X improvement in my productivity. As long as my constraints are in a good place, as long as I have a clear idea of what's going on. And but I but I will say that there's also times in which I've spun my wheels in odd ways that I wouldn't have otherwise without
Carter Morgan (57:14)
Yes.
Nathan Toups (57:15)
LLMs.
and again, I'm not against it because I I do think I I do agree with the Osterhout idea of like the design it twice thing. And I'm I'm I'm actually I spent a decent amount of time like using LLMs as a rubber ducky, thinking through problems that I'm working on, looking for falsifiable stuff. I will tell you, every time I deviate away from using sharp tools.
Making sure that I have good fitness functions in place. Anytime I deviate from that, that's where we get into like bad places with LLMs. But if I spend a time up front in being like, what falsifiable things can I create as I go? Right. And but by falsifiability, I mean if I make a claim of the way that the system should function, can I make something that says it does or does not function that way? Right. It's very test-driven development sounding.
But for me, I I've been spending a lot more time. What I've done in my best jobs in the past, but doing this now is building little command line tools. Because I there's a lot of stuff that I don't want LLMs to have flexibility on. And once I kind of figure out what a flow is, I'll build a tool that gives it an instant constraint. and then all of a sudden I can trust the tool more. Right. So I can be like, okay, I've figured out that I always want these five things to operate anytime I'm making a decision or
Carter Morgan (58:20)
Right, right.
Yes.
Nathan Toups (58:41)
maybe I have a age a sub agent that is a defender of everything that's in our ADRs or or our spec div driven development. And what it does is it's in its context window, it like slurps all that stuff up and then compares what code changes we've made. Does it meet alignment with or is there a contradiction? Right. I think these kind of little games that you can play can be really useful for looking for blind spots that I have. Maybe I've forgotten, like, yeah, we agreed.
That we would never structure user data this way because of this ADR that we have. And Claude obviously was missing the context there and is trying to push this thing through. And I forgot about it myself. And I have this other subagent that's kind of like sticking up for the docs, right? Or whatever. Those are, I think it but again, you get back to these like Unix philosophy where I think it was it's Matt, Matt Pocock that has brought this up really well. He tries to keep his context windows as small as possible.
And so he like he knows that the context windows are best when they're kind of you know three quarters empty. and so he's like, Well, can I play a game in which I know that this is only pulling in context? It's really loses its full memory every time. So can I play this game where I've got this excellent paper trail? I have these very clear instructions on how to bootstrap yourself, and I have a very clear question of like the next thing I want to get done. And the more I've been playing that game, the more I'm like,
Carter Morgan (59:39)
Right.
Nathan Toups (1:00:09)
Yes, this is this sort of advanced beginner, you know, junior dev idea that we've been bringing up is that that is a great use of these tools, right? Is that you you can go in and give it some unique perspective on a bigger state of things that I'm keeping track of and it can do those like sort of more focused jobs really well. If I ask it to do my job, it starts to do a bad job, right?
Carter Morgan (1:00:30)
Right, right.
We we've been having not disagreements at work, but just a little like we we actually just we're we want the idea of like especially for stuff that like like low priority work, we want agents to be able to just kind of autonomously work on this stuff. which I think is really, really good. and we looked at kind of like a lot of like the managed solutions and didn't like any of them. And so we just had some old laptops and we're just like just just set cloud running on a loop on this laptop, right?
And leave it plugged in all the time. Let's see, let's see what that does. Right. and so, and we've got it hooked up to linear. So as tickets come in that have a special label, it'll pick up those tickets and start working, which is good. But there's some kind of work, like for example, with some of these queries that we have to rewrite because they it turns out they're they're really inefficient. And I had had an engineer who was like, great, like I'll, I'll we call the the laptops the ponies. Like I'll have the ponies work on this. I was just kind of like,
The ponies are going to have to like first the ponies can't connect to the database and run the explain query. So like we're gonna have to run that for them, give it to them. And then when they run the code, or then when they rewrite it, we're gonna have to pull it down and we're gonna have to test it, and we're gonna have to run the explain again to make sure that it works, right? And I'm just like, at this point, like like we're we're
We're farming out so little of this. And like I kind of hate this idea that like the machines will generate all the code and then I will pull it down and test it. Like I I don't I don't have that expectation with any other developer. Like if any other developer was submitting code and was like, I didn't test this, can you pull it down and test it for me? I'd be like, what are you talking about? Like test your own stuff. And so that gets into a whole other thing where like I think what we need really need are feature branch previews.
especially 'cause like a lot of what they handle is like UI improvements. and like that's really easy to confirm just by clicking it in a feature branch. But to do that, I think we need to be on Kubernetes instead of ECS and it's all a big thing. anyhow. but yeah, just like, I don't know. I I like the idea of these things to be autonomous. They need to like actually autonomous, like a junior engineer at, you know.
Nathan Toups (1:02:41)
So
Yeah, I'm not
quite there yet. I have some pretty cool s stuff that I'm I'm working on internally. the CTO at this company that I'm working with has some really neat tools that he's been working on and I think he's gonna release it to the public at some point. It's this idea that you can sp makes it really simple to spin up agentic workflows on virtual machines that are ephemeral. So you basically you you do a little bit of upfront work, but your entire dev environment,
Carter Morgan (1:03:07)
Nice.
Nathan Toups (1:03:14)
gets spun up with Tmux and a bunch of other kind of cool things. And you can give it a set of tasks and it kind of like heaps the scope within what it's allowed to do. So it's super locked down. And you can give it agentix stuff to go off and do on its own, but you still have full control and you can be the sort of like, you know, human in the loop part as needed. and I've been actually falling in love with it. So it's so funny, like I'm dusting off my old dot files and I'm even building my own skills repository.
Because I I want to make it super easy for me to like spin up a virtual machine from scratch and just have a productive work environment for Claude. which again makes all kinds of things nice. and yeah, I I I don't know, I think we're gonna be continue to explore these areas. And this actually gets us into the our our final chapter for this, which is evolving design decisions. So I loved this section because I I I end up having this conversation a lot, which is you know.
Carter Morgan (1:03:49)
Right.
Yes.
Nathan Toups (1:04:13)
Software is a it's always a moving target for how the business logic works. Part of that is because you discover the actual needs of the business as you're building. And so therefore you're like, I thought this was the app context, but actually it should be divided this way. Some of it is that the business needs themselves change, right? That a new competitor comes to the market, some new idea is out, new customer expectations enter the conversation.
Carter Morgan (1:04:33)
Right, right.
Nathan Toups (1:04:42)
And therefore you realize the decisions you've made in the past are not serving you anymore. Right. You need to make some modification. And this chapter is awesome because it talks about migration paths or you know, what happens when an organization grows and now you have to split teams up, or you know, like there's all these like really kind of juicy, hard things to think about where you're like, yeah.
Carter Morgan (1:04:54)
Mm-hmm.
Yeah.
Nathan Toups (1:05:08)
This is actually three
app contexts. Or we thought this was two separate ones was actually one app context. It's now we have this like tightly coupled two app contexts and yeah. I I I thought this chapter was my favorite so far, actually.
Carter Morgan (1:05:21)
Yeah, no, it's a great chapter. and again, I like I think there's a lot of overlap with this and software architecture, the hard parts. and yeah, like I think that's fun. That's I I think that's fun about like I I wonder if the culture's changing a bit. Like we used to really reward job hopping. And I feel like I'm seeing a little more in the water these days that like now we want people at their companies a little longer. We want people to kind of live with the decisions they make. I don't know if that'll be true. And it's also like
This is an insane industry where like if you meet someone who's been at a job for five years, you're like, Whoa, like you're like the old man on the mountain. Right. And so we might just be moving from somewhere where like three year tenures is passe, but four year tenures is what we actually want. anyhow, we gotta wrap up. I I gave go, go ahead.
Nathan Toups (1:05:56)
Right.
Yeah, but right before we do though, I I think
one last little concept from chapter eleven. I remember at the beginning of the last episode, you were kind of like we were talking about difference between core and generic and supporting. And I loved that this chapter sort of s said, Hey, not only is there a difference between core generic and supporting subdomains, but you could transition you might transition from one to the other, right? You might have self hosted something and you decide you just the off the shelf tool's so amazing now. We should transition.
Carter Morgan (1:06:32)
Yeah, yeah.
Right, right.
Nathan Toups (1:06:38)
To some generic implementation, or vice versa. Like they even brought up an example, I think it was from generic to core where Amazon, right? Amaz yeah, they they they talk about Amazon Web Services and they go, you know what? Instead of us buying off-the-shelf stack and rack servers, what if we built an entire business unit around this new idea of API first infrastructure as code sort of driven infrastructure and made a c an entire core business out of something that was
Carter Morgan (1:06:46)
yeah, yeah.
Nathan Toups (1:07:08)
You know, before that it was just a commodity thing. It's like, I'm gonna go talk to Dell or O some OEM and buy some stuff and purpose build it for Amazon dot com. but no, they they kind of and so I liked that they kind of walked through like how does something go from generic to core, core to supporting, or supporting to generic and yeah, it just was nice.
Carter Morgan (1:07:15)
Right, right.
Yeah, I I like that idea
too. Cause you're right, like something that's really critical now might not be in the future. Or, you know, yeah, might become a commodity. Something that you weren't that interested in might become really, really important, right, to your business. So I again, all about judgment and you know how these things evolve. As far as hot takes go, I mean, to me, you know, you've swayed me, Nathan. I thought the event sourcing model seemed insane. And the more I think about it, I'm like, you know what?
They're crazier ideas. And I could see this being like incredibly valuable one day. So I pity the poor junior engineer who winds up on that team and is like, this is how software is built, because they're gonna be like, they didn't teach me anything like this in school. but good stuff. what about you, Nathan? Any hot takes?
Nathan Toups (1:08:07)
That's so funny.
I didn't have any hot takes this week. I I just c I couldn't think of anything that was like a zinger. I was I don't know. I I I didn't have any of the criticisms that I had the first week or or you know, sort of like I all the things here are like in my wheelhouse. I like to think about software architecture type stuff and yeah.
Carter Morgan (1:08:13)
They ooh, we agree completely.
Right.
Is that the sign of a great book, or is that the sign of a book that maybe I didn't try hard enough? Maybe it should have shocked us more. Maybe. Like okay. So as far as what we're gonna do differently, me, we talked about this outbox pattern. We have this outbox pattern. We're in this weird situation where, like, because we're mongo migrating from Mongo to Postgres, we had to treat Mongo the source of truth, and then we were replicating the Mongo changes to our Postgres instance.
Nathan Toups (1:08:36)
Or maybe I didn't try hard enough, you know? That's the other side.
Carter Morgan (1:08:57)
We're finally at the point where we can deprecate Mongo collections. And so, but the whole point of the outbox pattern is that you can do things in the same transaction. And we actually haven't been doing any of that because we've been writing to Mongo. So as we switch and write to Postgres, I need to bundle those transactions with our currently existing Outbox transactions, which are on Postgres because that was a net new concept. So I'm gonna get that working. How about you, Nathan?
Nathan Toups (1:09:20)
So mine, this one sounds so simple, but in the section that he talks about designing for change, this idea that you need to periodically reevaluate your design and say, Is this serving us well? I just hadn't thought about being like, I should put that on the schedule. Like I should maybe look at this once a quarter and be like, Is this serving me? And then sign off on it and being like, Yeah, this is still this is still doing great. Or I'd be like, you know what? I don't think so. Or I think the stress cracks are gonna kick in next quarter.
Carter Morgan (1:09:36)
Yeah, yeah.
Nathan Toups (1:09:50)
with what I know is on the roadmap, right? and so I think I'm gonna try this. I'm gonna actually add some events to my calendar to reevaluate some of the design decisions I've made on this data project, you know, in another couple of months. And and just yeah.
Carter Morgan (1:10:03)
I I like that. I
I think so much of software engineering is just inertia, right? And I think d d taking a step back and being like, okay, let's let's actually think about this. Is this doing what we want it to do? Is underrated. okay, well that takes us through the week. we will be back next week with the or with with the the final third of this book. And yeah, you can always find us at wait, where who do we recommend this book to? I I didn't do the wrap-up.
Nathan Toups (1:10:09)
Yeah.
Right.
it's all good.
Carter Morgan (1:10:33)
I
I I'd say like if you're looking for more sophisticated ways of constructing software, this is for you. Like again, that that event source domain model was really interesting to me. If you're trying to break out from like just basic crud, like this is a good book, you know, dip your toe in the water a bit.
Nathan Toups (1:10:48)
Yep, I agree. The I my my recommendation doesn't change from from last week, which I said, you know, senior plus engineers and leadership struggling with building alignment on stuff. I also think that this gets into if you're a fan of the ThoughtWorks books, right? If you're a fan fan of Neil Neil Ford and Mark Richards, this is a nice compliment, right? This should be on the shelf right next to DDIA, fundamental software architecture.
Carter Morgan (1:11:06)
Yeah, yeah.
Nathan Toups (1:11:15)
This book should sit up there too if you're kind of getting into domain driven stuff.
Carter Morgan (1:11:19)
High praise. all right. Well, you can find us on Twitter at Bookerflow Pod. You can find me on Twitter at Carter Morgan. You can go to bookoverflow.io, see our website and the schedule, and you can find Nathan and his consulting work at rohorobotto.com. We'll see you later, folks.
Nathan Toups (1:11:35)
Yeah.