Crafting Code Podcast
$ cd episodes/055-api-categorization
~/podcast/episodes/055-api-categorization $ ls -1a ~/podcast/episodes/055-api-categorization $ cat episode-summary.txtKnowing your audience is good advice for APIs, not just public speaking or selling your ideas. Providing separate APIs for different purposes can make each one much easier to manage, especially when it comes time to roll out updates. In this episode, your hosts discuss how we like to categorize our APIs, how we deal with versioning, and why you might want to follow these patterns too.
~/podcast/episodes/055-api-categorization $ cat themes.txt ~/podcast/episodes/055-api-categorization$ cat transcript.txt
[00:00:16] Allan Stewart: Welcome to the Crafting Code Podcast, where we discuss the importance of doing the right thing at the right time with the right tools. I'm Allan Stewart, a software architect. Lately, I've been thinking about the need for a foundation of principles and intentionality when trying to create or alter a culture.
[00:00:34] Dave Adsit: I'm Dave Adsit, a VP of engineering, and I have been thinking about lean, agile scrum product strategy and the importance of aligning incentives to desired outcomes in an organization.
[00:00:48] Allan Stewart: Our topic for this episode is API categorization. This is a topic that, or a concept that you introduced me to. Dave, so tell our listeners, what do you mean by categorization and why would you want to do this?
[00:01:02] Dave Adsit: Well, APIs are a very common thing in software development. We use APIs for everything, right? We expose APIs to our customers. We expose APIs between our systems. We consume other people's APIs. And each of these APIs, for me, fits in a different category. Whether it is... Who the consumer, who the intended consumer is, is one axis. And what is the level of visibility is the other axis for how I like to categorize APIs.
[00:01:39] Allan Stewart: Yeah, it's kind of the programming analog to knowing your audience. At least that's how I think about it. Like there are times as a software architect where I have found that there is the same concept or same problem that I have had and I need to present it differently. Depending on who my audience is. So if I'm presenting to developers and say, hey, this is what we're trying to achieve as a bunch of developers, then they need a different level of detail. They need a different kind of information than when I'm talking to product managers or than when I'm talking to an executive team. The same kind of concept comes up in like public speaking, right? Knowing your audience is an important way to be able to communicate effectively with them. And I feel like this is a kind of a programming analog. I agree.
[00:02:27] Dave Adsit: And what it really comes down to is what are the needs and capabilities of your customers, your consumers, your API consumers, you know, the people this API is for. So if we just jump right into it, the three different types of consumers I think of when I categorize APIs are first our customers. And when we think of an API, probably the first thing you think of is I'm going to build an API that's externally available for. Our customers. It's a reporting API. It's an integration for API, something that our customers are going to use. And, and there's specific requirements and constraints that come with building an API that's going to be used by the companies or people that you sell your product to. The, the second level is the second category is the system API. And those are APIs that we're building, not for our customers, but for our internal use. So we're building a microservices system. I run a service, you run a service, you need something from me. I expose an API that you can then use. Right. That is the second type. And the third, I call the context, the bounded context, the context, maybe the team API. And those are APIs we make for ourselves. So in this case, I'm talking about, I've got a microservice that I'm building and you've got a microservice that you you're building. Well, my microservice. Has a front end and that front end needs to be served data. And I'm going to serve that data through an API. And now we're, we've got three different types or categories of API that each have different characteristics.
[00:04:09] Allan Stewart: Right. And in that final one, the context one, because it is the team that is owning it. This is the case where you're writing the front end and also the backend. Right. Right. So that's one axis. The other axis. Is the visibility. Right. And this basically is just, is it accessible on the outside internet or do you need to be on some kind of like internal VPC or something to access it? Right.
[00:04:37] Dave Adsit: Yeah. Yeah. I that's the other category is I, when we're deploying to a cloud or an internal data center, some of the stuff that we build is only accessible if you have direct access to our network. And some of it is just access. We're out there in the internet and the wild, scary world. And so that also gives us different constraints, right? The way we build an API that is only internally routable and accessible. We're going to probably treat security a different way. For example, maybe we're going to do. Pre-shared private keys or secret keys versus building a fully robust. Authentication. And authorization system. You know, maybe we say everybody who has a key. Everybody like we have four consumers. So if it's a system API, we've got four consumers, each of them got their own API key. We can track based on key who's using it, whatever. Easy peasy. Uh, and if I put it on the public internet, I'm going to have to be pretty careful about who I let access this and how, so that they don't do nefarious things with our data. So given that you've got. Two axes. Two. Three by two. That's six quadrants, quadrants, six areas that an API could fit in. Yeah. Um, five of those make a lot of sense. And one of them is kind of, I'd like to see it, but I haven't. So we can have either a public or private bounded context API. That's owned by my team used by my team. It's internally routable or externally routable. Great. Uh, we can have a public or private system API. Sometimes parts of my system. Might need to route traffic through the internet. Sometimes they route traffic internally in my data center. Both of those are very reasonable. Uh, and then we probably only have a public customer API because if it's an internal or private customer API, how do they get access to it?
[00:06:42] Allan Stewart: Right. Yeah. And I think, I think there's good reasons for various ones of those, right? So like, even though your team context level API shouldn't really be used by anybody else. Right. Like your team is the only one that should really be accessing it. It's going to happen probably from like a web or a mobile front end of some kind. And so it has to be publicly addressable, you know, so that the browser can actually connect to it. So it is public. I think you originally turned it as public and internal. I think that that's better than public and private in some ways, because it's your, your public context. One might still be private in as much as you're not letting others. Other people use it. And then, like you said, it might have a different, you know, each one of these have, have different ways that you access it. Right. Different security measures. Right. And so like with the, with the context API, that's powering a, a web front end, you might have some kind of like a different bearer token or even like a authentication cookie that is shared across many parts of your entire system. And that is treated differently than say a system. API. Or a customer API that has a different kind of security pattern. And, and then there's other things that go along with that too. Right. Like where does the data come from? What kind of caching is available? If you've got like a reporting API for customers, it might not be, you know, real time up to date. It might be just, Hey, as of, you know, every so often, like, you know, we've got like a rolling window, like every, every day, you know, that anything is up to date. At least since. Midnight or something like that.
[00:08:26] Dave Adsit: Close of business yesterday. Yeah. Right. Yeah. So let's take a dig in a little bit more on the differences between the consumers. The, uh, the, the reason that I like to create a context API specifically is if it's owned by my team and only accessed by my team, there are no constraints on how often I change it. Not really. Right. If I'm doing, if I'm doing a. Continuous deploy, continuous delivery, I'm, I'm shipping code five times a day into production. I can change the shape of that API every single time. All I have to do is deploy the API and the front end together. And because I know there's no consumers, but us it's okay. If it changes all the time at a very rapid case, a very rapid cadence, and that allows us to do some interesting things. Like I can follow the back ends for front ends pattern where I, in that pattern, I say, here's the front end that I need. And it needs these data, this data to like fill the form, whatever. Okay. I'm going to create an API endpoint that returns that data and exactly that data with nothing else. And I know I can just change it as the front end changes. If the UI changes and I need more data, I can add it. If the UI changes and I remove data, I can remove it from my. I can add it to my response, my backend response and the back ends for front ends pattern where I custom build that backend response to meet the needs of that front end as it exists right now. And that allows us to have really, really lightweight responses. Um, so that can be more efficient. It can be better on mobile, et cetera. Right.
[00:10:15] Allan Stewart: And you can choose how you want to aggregate data for certain calls. Because. Hey, this, we know exactly the purpose of this particular page or the reason why it's being called. And so you're, you're tailoring it to your exact need rather than kind of an arbitrary, like, I think over the years I've encountered people who want to do, you know, a really pure or true rest functionality. Right. Um, yeah. Or, or another example is I I've seen a lot of people who are like, well, you have an API and so therefore you might. of all this documentation. It's just like, it's just extra weight. It's extra noise. You might get it for free, but as we all know, you know, there's not really a free lunch.
[00:11:30] Dave Adsit: I've used some systems that had those before. I've worked on systems that use those types of tools before. And we always turned them off in production because you never know what somebody's going to do if they get access to that documentation. And so it wasn't really super useful to us anyway. Right. So that is that, if you have that dedicated API, which you probably do if you're building a web application, it's got some really nice characteristics that allow some really good development patterns. If you're building a more complicated distributed system and you start building system APIs, then you get some slightly different behavior and constraints, right? So if I've got a system API, one of the things that I want to, basically because I'm exposing that to other teams, presumably, I've got a big enough company, big enough organization that I need to have multiple teams building different things. And they're going to need to share some stuff, either behavior or data or something. And I want to do that through APIs because that gives me some ability to abstract away the implementation. I don't want to give anybody access to my database. So I better build them an API if they need my data. So with a system API, I can't change it every day because I've got consumers, on other teams that are doing things with that API. They're relying on it. I've basically made a contract with them that this API will be available and they need it to be available. And if I decide I want to change it, well, I can't necessarily change it because they can't necessarily drop everything and implement the new version when I want to ship it. So now I've got to introduce some more complexity to, to the API interaction. And that means probably what I want to do is track all of my users. I said earlier that I want to give every consumer a different API key. And that's for a couple of reasons. That's for partially for security, but partially that's so that I can track who is using which versions of my API. Right. And when I ship a new version, I'm going to probably have to stand up my VNext of the API and tell everybody, tell everybody about it and incentivize them to use it or ask them to use it or whatever. Say, please, please upgrade to my new API so I can turn off the old one. It's got these new function, this new functionality that's going to make things so much better. Please use the new API. And then if I'm tracking the API keys that I've issued, I can then see who's moved and who hasn't. If I'm doing decent observability in my system, which I should be as well. And that allows me to see when everybody's on the new API, and when I can deprecate the old one.
[00:14:14] Allan Stewart: And I think about that, like it's not that you wouldn't do these things for other kinds of APIs necessarily, right? Like you might want to have for uniformity sake, you might want to have the same kind of security profile. Maybe you don't go with a shared key. Maybe you do have a whole key exchange or. A lot. Yeah. Or like create the key and you'll be able to see it once and we're starting to have it. Thanks.
[00:14:58] Dave Adsit: Thanks.
[00:14:59] Allan Stewart: Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. Thanks. where because it's in the system, these are all people that work for your same company. And those teams are not always incentivized and aligned towards the same objectives, right? Because they're spread out into different teams. And so they're doing different things, right? And they have different bosses that are asking for things. But as a company, you tend to be more aligned than the alignment of some other third party that you may not even know really who they are, especially if you're allowing for things like, oh yeah, just auto generate your API key and go to town and have fun with using our API, right? Like you might not have a clean way of communicating with all of these people and letting them know about some kind of change that you want to perform. Well, and if you think about it,
[00:16:05] Dave Adsit: for your system API, you've got between a handful and possibly on the upper end, dozens of consumers. Worst case scenario, most of your users have moved to the new version and one is hanging onto the old version. You can go crash their standup or you know their boss, you can take them to lunch and say, you know, it'd really be helpful for our department if your department would upgrade to our current API. You know, you're missing out on all of these you can apply some social pressure, right? There's a lot of things you can do inside the system because you are part of one overall system. Whereas when you get to the customer APIs, you're talking hundreds, thousands, even millions of consumers of that API. You're going to have a lot harder time tracking them all down and getting them to move.
[00:16:55] Allan Stewart: Even if you're observing, right? If you have really good observability and you can see, oh yep, we know it's these customers. There's still limits to what you can do, right? Like, I guess. You know, send them an email, right? Or you can get really clever and start building things into your API. Like, oh, if you're too far, you know, after you hit a deprecation date, it's going to stop working. Or like you start getting some kind of a 400 error percentage based and, you know, you start getting them a few at a time and you get more and more and more until finally it's just shut off. I think there's clever things you can do, but you might still be breaking them and they just don't have the time. Or interest to make a change. And so somebody is going to be impacted by that.
[00:17:40] Dave Adsit: Yeah. So if you think about it, the, the acceptable maximum cadence of change is different for these different types. If it's a context API, we've already said, change it multiple times a day. It's yours. You're using it. Fine.
[00:17:53] Allan Stewart: Right. I think the only limitation there with your context level API is just the things that you own, right? Like if you deploy out a single page app and you know that it takes, a few hours before or days, even before everybody's refreshed and they're onto the latest, well, then you might have a little bit of gap that you have to have backwards compatibility for before you make a breaking change, but you don't have to announce it to anybody. You just have to wait and then go on your way and you can make that change whenever you want without having to tell anybody else about it.
[00:18:25] Dave Adsit: Yeah. And with a system API during initial development, it's probably the same, right? We're working out the contract together, but then after I've published it, after, you've integrated with it, I'm probably not going to be able to change it more than on the cadence of weeks, because we have to coordinate work across multiple work streams in order to do that. With a customer API, I assert that your customers are not going to want you to change your API more than quarterly. And they probably don't want you to change it at all unless they're the one who requested the new functionality. But if you're changing your customer facing API more than once a quarter, you're going to end up with some frustrated customers, particularly if you are following good API versioning habits, right? We talk about your API for the context, your bounded context API, you might have to have a vCurrent and vPrevious if it takes a few hours or a day for all of your all of your clients that you deployed to update. If you're working on a system API, and you want to create a new version, my rule of thumb is don't ever support more than three. You want vCurrent, of course, vPrevious, because not all of your customers have moved, and vNext if you're developing another one, right? So you might have those three. And you want all of your customers to be on vCurrent with a few testing vNext with you. And anybody who's on vPrevious, you got to get them to move so that you can deprecate it, delete it, and
[00:20:03] Allan Stewart: now create another one. And to be clear here, I think you mean consumer, right? Right. The consumers of your API, because in the system context, these are other teams, as opposed to customers external to the organization.
[00:20:19] Dave Adsit: Yes, that's right. The customers are consumers of your API inside of your development ecosystem, as opposed to your actual customers who you also probably want to have limits on how many API Because your system is changing, and finding a way to support a really old API for your really new functionality is an onerous change. So I like to do those as names, maybe. I've named API endpoints according to whatever the context is, slash vCurrent, vPrevious, and vNext. Those are names that are very, very communicative for people inside of your system. Not super great for customers. They don't really know what that means. And so for customer facing APIs, I usually like to use the quarter and year that it was published as the name. And I usually just throw that in as a URL part inside of the route. Which gets me to a question of versioning. If we're talking about versioning APIs, version them? Do you version individual endpoints? Or do you version the API as a whole?
[00:21:39] Allan Stewart: That's a tough one. And I think, as I have reflected on this, I think a lot of it has to do with volatility. And at what level do you see a lot of change? So if you've got really stable APIs that are changing slowly, I can see an argument for doing versioning per endpoint. If you're doing a text API and it's just you, well, then yeah, you almost don't need any versioning at all. You just have to be careful that you're not breaking things, that you're keeping it backwards compatible in your deploy window. And so doing it per endpoint or even options on an endpoint, that probably works just fine. But yeah, as you go further out in the scope and there's more people interacting with it, those ways of communicating, it gets really confusing if it's like, oh, no, on that endpoint, you need to be on V5, but you should be on V2 for this other endpoint and V3 for this one. That just gets confusing for people to remember. So updating the entire API at once, it makes the communication easier and the clarity better. I think that makes sense. And I like what you're saying about how you name it. Yes, absolutely, we can use version numbers. There are definitely benefits to something like an increasing numeric version. It's why SemVer is very popular, the semantic versioning. But I really like what you said about having information built into the version. If I tell you that the NPM package that I'm using is version 8.6.2, it tells you something. There is information embedded in there. But if I told you that it was, from 2004 versus 2025, that's going to make a bigger difference to you. There's meaning that's communicated in there as far as, is this old? On the other hand, if you have a stable API and you don't make changes to it yearly and people are still using the 2019 version of your API, maybe that's fine. But it's kind of a double-edged sword. If you put the year in there and maybe which quarter or whatever, they might start asking, well, is this old? Should I be upgrading? This is five years old. Should I be making a change here?
[00:24:15] Dave Adsit: That is one of the few forms of social pressure you can apply to your vast army of actual customers who are using your API. Why are we using an API that's 11 years out of date? Is there a new one? Oh, there's a hundred new ones. Okay. Maybe we should upgrade. Okay. So
[00:24:44] Allan Stewart: thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like we're really thinking like Because in addition to it being confusing, it's really easy to just have two routes that go to the same thing. It really is. And so you can ratchet up your marketing speak and be like, hey, looks like you're four years out of date. Yeah, the API is actually exactly the same, but we can tell that you've been using this without thinking about changing it for a while. Right.
[00:25:26] Dave Adsit: So one of the things that comes up all the time is the idea that if we have an API, then we can just use it for all of these purposes. And as we've talked about these different categories, you can see that there are some problems that come if we use an API incorrectly. If we take our team or context API and we let our customers use it, that is going to break our ability to evolve our product. Because now we have to communicate with our customers. When we want to change the API so that we can add new functionality. The same happens if we let our system users, if we, if we treat a context or team API as though it were a system API, we get the same kind of behavior. Maybe not as bad, but still we're going to impede our progress on delivering new value to customers. If we only use our customer API to build our product, that's going to slow again, slow down our ability to build new functionality in the product. And so for me, it's really important that we take this concept of API and break it down into the purpose, the category, the type of API that we're actually shipping and avoid that false reuse. I've heard people say, Hey, when we do this, when we build this integration between these two systems, let's make sure we do it with an API so that then we can give that API to customers later. Like, you know what? That's actually love where your head is around. Exposing functionality to customers. However, if we do that, it will impede our ability to evolve the system and especially the integration between these two components. So I think of that kind of improper API use or as a form of false reuse. We've talked before about how reuse is the false idol of pro of the programmer. Like we, we pursue, we pursue reuse before we've even gotten use out of something sometimes. Yeah. And it's, it's often building for reuse is a recipe for over-engineering something. So I try not to do that. I try to be clear on what type of API we're building so that we are not over-engineering and not wasting a bunch of time and not impeding our ability to create new value. Like it's all about creating new value for customers.
[00:27:46] Allan Stewart: Yeah. I think it's important to recognize the speed of change. Like what cadence do you observe change and create different APIs? So one of the things that we do at the company I'm working at right now is we, even though we have just a single team, we have a split in our context APIs. So we have separate endpoints for mobile, for our primary web app. And then we also have the customer portal web app. And these are three separate deployables. And we've intentionally broken them up. Even though some of them literally have controllers that use the exact, like we will copy paste code from one to the other because it's exactly the same need. But we've separated it because that's not always true. Sometimes the mobile app needs a different method of aggregation of data. Same with the customer portal side. It doesn't, we need to restrict what kind of data comes back. Yeah. We've got to be able to do this in the JSON payloads in a different way than is needed for the regular users of the primary web app to be able to do what they're doing. So even though all three of these APIs fall into the same bucket, right? The same API category, they're all public context as far as how they're categorized. It still was helpful to us to break them up. It gives us better visibility. It gives us better ability to build what is needed and be able to change it at the rate that we want to change it without, without worrying. It's like, oh, well, is that going to break the mobile app? No, it won't break the mobile app because they don't use this API at all.
[00:29:42] Dave Adsit: So when we talk about all of these different needs and purposes and customers, consumers for APIs, there will always be someone who says GraphQL solves all of this for us. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Right. Because GraphQL allows you to decouple front end from backend. And the reason you want to decouple front end from backend is because you have aligned your teams around specialties. You've got your specialist front end devs who don't want to talk to those backend people. And you've got your specialist backend people who don't want to talk to those front end people. And so they create this layer that allows for lack of communication. And honestly, what that does is it slows down your ability to deliver, slows down your system, because even if you have GraphQL in place, you still have to expose the resolvers and you have to communicate and document all the resolvers that are available in the system. And you're running extra complexity as well. You've got to have some Apollo in there and you've got to have some tools in there that actually make GraphQL work. And so it's not a good fit for a team or context level API.
[00:31:18] Allan Stewart: I think there's even... There's an argument there that you're not acting as a team, right? Like you're pushing what ought to be a team thing to a system level, because you are... Even if you are team in name, if you are acting as sub teams that are separate and you're not communicating, well, that's not a team.
[00:31:41] Dave Adsit: Correct. And that actually does bring up one context in which I believe GraphQL is the correct answer. That is where you have a single backend system and many, probably more than five, different front end systems. For example, you're building Netflix and you've got a Samsung TV player, an Android phone player, an Apple TV player, an Apple phone player. You've got your own custom player that you've built and sold at trade shows. You've got... The Roku one. You've got to make it work in Chrome, on Windows. And Linux and Apple. And you've got to make Safari work. And you've got all of these different front ends. And they all have the possibility of having slightly different needs and communication patterns, but they're all doing the exact same thing. And so you might have 15 different specialist front end teams building apps that all consume one API and have to consume it slightly differently. Maybe you need to have a lot of really small... Small requests. We talked earlier about a RESTful API versus a fit for purpose API. Maybe you've got a lot of small requests versus maybe the system you're working on is optimized for larger payloads and fewer API calls. And so if you have that kind of a system, then you might need a tool like GraphQL to help bridge that gap. You would end up building something like that if you weren't just using GraphQL out of the box. And if you are building that kind of a system, then it's a good fit. Chances are you are not building that kind of a system. Most of us are not. And so for most of us, it's not a great fit because it doesn't meet an actual need we have. It's not a good fit. We talked about the unnecessary excess complexity that it introduces into a context or team API. It doesn't help when you're talking system to system either, because you've got specific constraints and requirements around the system to system communication. And most of your customers are probably not sufficiently sophisticated to use a tool like GraphQL when something more like a restful API would make more sense for them.
[00:33:52] Allan Stewart: Another place I think is a good example is something big like GitHub, where this time it's a customer facing thing, but you know your audience, right? Like you've got a bunch of programmers that are interacting with this and it's such a huge audience that you can't possibly know what the various. Needs are for all of the different kinds of apps. So it's almost the inverse of the Netflix example, right? Like with Netflix, it's the same, the same backend powering essentially the same experience, but across all these different devices that have different, different needs. But with GitHub, it's more like we have no idea all of the variety of things that people are going to be doing, but they're all pulling from our data. And so we're making it available in a very flexible, generic way. But they're also big enough that they can do, you know, caching and figure out how to solve the N plus one query problems and some of these access patterns and, and, and whatever else is, is needed to be able to host a big GraphQL instance like that, because, because you don't know how it's going to be used.
[00:35:05] Dave Adsit: Well, and that's where GraphQL evolved, right? Is GraphQL was built by Facebook before they became meta. And it was the social graph query language that they exposed to people who were building apps that needed arbitrary data about the social graph. And they didn't know how it was going to be consumed. And so they had to expose a lot of things. And we've all, we already know it's not a good idea to expose your database to your customers. You're not going to give somebody a connection string to your Postgres instance and let them just run wild in there. But by putting an API in front of it, by using a tool like GraphQL, you're going to be able to do that. So you can create some level of constraint and some level of protection around the system. You're abstracting away the implementation of the system in the query language that's exposed.
[00:35:53] Allan Stewart: Yeah. But that that's not a catch-all though. Right? So like the example that I gave earlier, we have a customer portal that needs a lot of the same kind of data. It's something that we control. It's like, it's the context API. But I can't allow that API to run. I can't really rely on it to really resolve certain data that I would allow this other consumer. Even though it's all the same team. So if I were using GraphQL to solve this problem, I'd actually have to have two separate GraphQL instances or some separation there to allow yes, this one can access some data. This one can't access some data. Which adds some complexity that may or may not be warranted depending on the use case. that I thought of as we're talking about, you know, kind of backing up into the discussion of API categorization, we also have another split in the APIs that we use, just because sometimes you want something that is very bespoke, something that's very fit for purpose, and you don't necessarily have all the choices. So if you are going to create some web hooks that let you interact with another system, well, you might not have a choice. You can't go over to that third party company and say, hey, I know you have this web hook subscription, could you please make it so that it will talk in a particular language for me? Or, you know, I wish you wouldn't send me XML, I wish you would send me JSON, like, you might not get that choice. Or could you please send that data to me as a mutation of GraphQL? It's like, well, no, you get a post that has some JSON, so there are cases like that, where there are specific constraints where you might want to separate things out. So we've got separate endpoints that have a different kind of API structure for things like web hooks. And that's different from our Zapier integration. We've got a separate set of endpoints that are specifically for our Zapier integration, because we know that it has a different set of constraints, and it updates at a different timescale and things
[00:38:30] Dave Adsit: about us really thinking about us really thinking about us really thinking about us really thinking about us really thinking you understand when you should use APIs of different types and how you should think about the constraints that come with the different consumers you can have for your APIs and make better choices about how to do system design.
Copyright © 2026 - Crafting Code Podcast